2014-06-15 9 views
7

Ich habe mich umgesehen, kann aber nicht genau das finden, wonach ich suche.Java: Methodenaufrufe in einem Array speichern und später ausführen?

Ich habe eine Klasse definiert, die eine Region in einem JPanel darstellen soll, auf die Sie zeichnen können, indem Sie ein gepuffertesImage der angegebenen Größe erstellen und diese Grafikbilder zu DoubleBuffer verwenden JPanel, und diese Region wird dann als Bild zum übergeordneten JPanel gezeichnet, was im Wesentlichen Panel-Bereiche erzeugt, ohne sich mit der verrückten Panel-Organisationslogik von javax herumschlagen zu müssen, die davon abhängt, dass alle Panels Boarder berühren. Dies ist im Wesentlichen ein Grafikkontext für Grafikwidgets, die ähnlich wie bei der Videospiel-Benutzeroberfläche verschoben/skaliert werden können.

Was ich versuche zu tun ist, ich möchte in der Lage sein, Methodenaufrufe zu speichern, um Operationen in der Grafikklasse zu zeichnen, inklusive der Parameter. Der Grund dafür ist, dass ich entweder zur Laufzeit oder im Quellcode Methoden mit den bereits angegebenen Parametern laden kann, die nur aufgerufen werden können, ohne die Kapselung zu unterbrechen, da die Elternklasse entweder direkt zeichnen muss zum pufferedimage, etwas, das ich vermeiden möchte, damit Methoden zur Laufzeit hinzugefügt werden können, oder die Methodenaufrufe zum Zeichnen müssen in der PanelRegion-Klasse selbst ausgeführt werden, was mich dazu zwingt, jedes Mal eine neue PanelRegion zu erstellen, was einfach nicht effizient funktionieren wird.

Was würde ich in der Lage sein mag einfach zu tun ist, so etwas wie:

Class graphics = panelRegion.getGraphics(); 
String methodName = "drawRectangle"; 
int xPos = 0; 
int yPos = 0; 
int width = 0; 
int height = 0; 

ImaginaryMethodClass method = graphics.getMethod(methodName, int, int, int, int); 
method.imaginaryMethodThatLoadsParameterValues(xPos, yPos, width, height); 

panelRegion.addMethod(method); 
panelRegion.invokeDrawMethods(); 

public void invokeDrawMethods() 
{ 
for(ImaginaryMethodClass aMethod : listOfMethods) 
{ 
aMethod.imaginaryMethodThatExecutesTheMethodWithTheLoadedParameterValues(); 
} 
} 

Wenn dies keinen Sinn macht, im Wesentlichen die einzige Lösung, die ich gefunden habe ist, können Sie Laden Sie Methoden abstrakt in Arrays mit der Reflector-Klasse, wenn Sie jedoch ausführen möchten, müssen Sie immer noch die Werte für die Parameter dieser Methode senden, was es im Grunde zu einem komplizierten Methodenaufruf im Quellcode macht. Ich möchte diesen Schritt entweder ausschneiden oder es so machen, dass die Methode mit den Werten, die ich gegeben habe, ausgeführt werden kann.

+1

See [Befehlsmuster] (http://en.wikipedia.org/wiki/Command_pattern) – Bohemian

Antwort

10

Was Sie versuchen, ist die Command Pattern genannt.

Eine einfache Möglichkeit, dies in Java zu tun, ist eine anonyme Klasse zu erstellen, die Runnable implementiert. Runnable ist eine Schnittstelle, die eine einzige Methode definiert: void run(). Sie können eine anonyme Klasse an beliebiger Stelle in Ihrem Code implementieren. Wenn Sie dies tun, können Sie auf jede Variable im aktuellen Bereich verweisen.

Java 8 macht es sehr viel einfacher, indem man syntaktischen Zucker für functional interfaces and lambda expression hinzufügt. Der Code in Ihrer Frage würde in Java 8 wie folgt aussehen:

Graphics graphics = panelRegion.getGraphics(); 

Runnable methodCall =() -> graphics.drawRectangle(xPos, yPos, width, height); 

panelRegion.addMethod(methodCall); 

Wenn Sie 8 verwenden Java noch nicht, der Code ist ein wenig verworren:

Graphics graphics = panelRegion.getGraphics(); 

Runnable methodCall = new Runnable() { 
    public void run() { 
     graphics.drawRectangle(xPos, yPos, width, height); 
    } 
} 

panelRegion.addMethod(methodCall); 

In beiden der (völlig äquivalent) Beispiele oben, graphics.drawRectangle(xPos, yPos, width, height) wird nicht ausgeführt. Es wird nur ausgeführt, wenn methodCall.run() aufgerufen wird.

Die Implementierung von panelRegion würde einen List<Runnable> mit den Befehlen erhalten, die es ausführen wird. Wenn es diese Liste ausführt, ruft es nur die .run()-Methode auf jedem von ihnen auf.

class PanelRegion { 

    private List<Runnable> listOfMethods = new ArrayList<>(); 

    public void addMethod(Runnable methodCall) { 
     listOfMethods.add(methodCall); 
    } 

    public void invokeDrawMethods() 
    { 
     for(Runnable aMethod : listOfMethods) { 
      aMethod.run(); 
     } 
    } 
} 
+0

Danke für das Hinzufügen des ausführbaren Bits; Ich habe bereits die Befehlsstruktur auf Wikipedia nachgeschlagen und obwohl es funktionierte, hatte ich einige Probleme. Dies funktionierte viel einfacher und zuverlässiger – user3743139

1

+1 für @Phillipp Antwort. Wenn Sie Objekte von Ihrer Methode zurückgeben möchten, können Sie Callable verwenden.

Graphics graphics = panelRegion.getGraphics(); 

Callable methodCall =() -> graphics.drawRectangle(xPos, yPos, width, height); 

panelRegion.addMethod(methodCall); 

Für unter Java 8:

Graphics graphics = panelRegion.getGraphics(); 

Callable methodCall = new Callable() { 
    @Override 
    public Object call() { 
     return graphics.drawRectangle(xPos, yPos, width, height); 
    } 
} 

panelRegion.addMethod(methodCall); 

und rufen wie:

class PanelRegion { 
    private List<Callable> listOfMethods = new ArrayList<>(); 

    public void addMethod(Callable methodCall) { 
     listOfMethods.add(methodCall); 
    } 

    public void invokeDrawMethods() 
    { 
     for(Callable aMethod : listOfMethods) { 
      Object ret = aMethod.call(); 
      // do something with ret 
     } 
    } 
} 
Verwandte Themen