2017-11-29 1 views
0

Wir sind damit beauftragt, ein einfaches Spiel zu machen. Jetzt haben wir das Spiel schon lange gemacht, aber ich habe gerade erst das join/host-Menü implementiert (mit einem JPanel in unserem JFrame, der nur einen Canvas enthält, der zum Rendern unserer Sprites/Shapes verwendet wird /etc.). Wir haben 4 JTextFields und zwei JButtons. Unsere Leinwand wird deaktiviert, wenn diese Anzeige so angezeigt wird, dass sie die Eingabe nicht stört (d. H. Mit ihrem Maus-Listener und dergleichen). Auf Windows-Rechnern können wir auf alle Kästchen klicken, wir bekommen den netten I-Strahl-Cursor usw., und wir können dort normal eingeben und dann auf die Schaltflächen klicken. Wenn dies jedoch unter MacOS versucht wird, können Sie nicht auf die Felder oder Schaltflächen klicken. Du bekommst den I-Beam nicht auf die Boxen. Es ist als ob sie nicht existieren. Wir können jedoch die Tabulatortaste verwenden, um den Fokus durch alle Elemente zu schalten, und können damit die Felder eingeben, die Schaltflächen usw. drücken, genau wie es mit der Maus möglich ist. Ich habe versucht, Fokus auf 20 verschiedene Arten zu verlangen, aber das schien nicht zu funktionieren. Ich habe viele andere Apps auf die gleiche Weise gemacht (JFrame> JPanel> JButton/TextField), und sie alle haben auf MacOS gut funktioniert. So etwas habe ich noch nie gesehen.JTextField kann nicht mit der Maus auf Mac OS fokussiert werden

Anstatt eine ganze Reihe von ganzen Dateien zu posten, werde ich sie abschneiden. Der erste ist unser Haupteinstieg, die Game-Klasse. Es sieht in etwa so aus:

public class Game extends Canvas implements Runnable 
    private JFrame frame; 
    private ConnectScreen connectScreen; 
    public getFrame() { /* get reference to frame */ } 
    public setFrame() { /* set the frame */ } 
    public void run() { /* game loop, calls render() */ } 
    public Game() { /* create window, add canvas to it, get reference to frame, instantiate stuff, etc. */ } 
    public void tick() { /* every frame this happens, just tells spawners to spawn stuff, etc. */ } 
    public void render() { 
     BufferStrategy bs = this.getBufferStrategy(); 
     if (bs == null) { 
      this.createBufferStrategy(3); 
      return; 
     } 
     Graphics g = bs.getDrawGraphics(); 

     ///////// Draw things below this///////////// 

     g.setColor(Color.black); 
     g.fillRect(0, 0, WIDTH, HEIGHT); 

     // SCREEN 
     if (!isPaused()) { 
      // THIS is where we tell the canvas to enable if we're not on the connect screen 
      if (gameState != STATE.Join && gameState != STATE.Host) { 
       this.setEnabled(true); 
      } 

      /* i omitted rendering from all of these, since it's not useful here. most say somethingScreen.render(g) or something like that. */ 
      if (gameState == STATE.Wave || gameState == STATE.Multiplayer || gameState == STATE.Bosses || gameState == STATE.Survival) { // render gameplay items 
      } else if (gameState == STATE.Menu || gameState == STATE.Help || gameState == STATE.Credits) { // render menu 
      } else if (gameState == STATE.Upgrade) { // render upgrade screen 
      } else if (gameState == STATE.GameOver) { // render game over screen 
      } else if (gameState == STATE.Leaderboard) { // render leaderboard 
      } else if (gameState == STATE.Color) { // render color picker screen 
      } else if (gameState == STATE.Join || gameState == STATE.Host) { 
       // if we are on the connect screen, disable this canvas 
       this.setEnabled(false); 
       connectScreen.render(g); 
      } else if (gameState == STATE.LeaderboardDisplay) { // render the leaderboard 
      } 
     } else { 
      pauseMenu.render(g); 
     } 
     if(!isPaused()) {} // renders the handler's things 
     ///////// Draw things above this////////////// 
     g.dispose(); 
     bs.show(); 
    } 
} 

Darüber hinaus gibt es in dieser Klasse nicht viel von Interesse. Hier ist die (abgespeckte) ConnectScreen Klasse:

public class ConnectScreen extends JPanel { 
    JFrame frame; // this is the frame from the Game class 
    JTextField _____; // there are 4 of these 
    JButton _____; // there are 2 of these 
    public ConnectScreen(Game game) { // the game is passed in to get the frame from it 
     super(); 
     this.setBackground(Color.black); 
     this.setPreferredSize(new java.awt.Dimension(Game.WIDTH, Game.HEIGHT)); 
     this.setSize(new java.awt.Dimension(Game.WIDTH, Game.HEIGHT)); 
     this.game = game; 
     this.mpSpawn = mp; 
     game.getFrame().add(this); 
     this.setFocusable(true); 

     /* set up each component */ 
     /* add each component (click handlers, etc.) */ 
     /* add panel to frame */ 
    } 
    public void render(Graphics g) { 
     super.paintComponent(g); 
     this.paintComponents(g); 
    } 
} 

Wir wissen, dass die Einrichtung von Elementen und so alle gearbeitet, da wir sie und verwenden, um alle auf Windows sehen, aber aus irgendeinem Grund, wenn wir es auf MacOS versuchen, es funktioniert nicht. Wir können sie tab-auswählen und/drücken, aber aus irgendeinem Grund können Sie nicht auf sie klicken, um zu fokussieren. Jede Hilfe wäre willkommen. Vielen Dank!

+2

Das Problem ist nicht mit dem Textfeld oder dem Betriebssystem, aber mit der 'BufferStrategy'. Swing-Komponenten haben ihren eigenen Malmechanismus, der nicht mit 'BufferStrategy' kompatibel ist - als allgemeine Regel sollten Sie NIEMALS eine' paint'-Methode direkt aufrufen. – MadProgrammer

+0

Stattdessen müssen Sie zwischen 'JPanel' und' Canvas' wechseln - mischen Sie nicht Swing-Komponenten und 'BufferStrategy' Rendering – MadProgrammer

+1

FYI: Es gibt eine ganze Pipeline von Funktionen, die Sie in Ihrem Versuch übersprungen haben" Wenn Sie die Swing-Komponenten manuell rendern, richtet diese Funktion den Ereignisverteilungsprozess ein, mit dem die Komponenten benachrichtigt werden, wenn Ereignisse auftreten. Ihr Versuch ist bestenfalls naiv und zeigt einen allgemeinen Mangel an Wissen darüber, wie die gesamte API funktioniert (nichts für ungut, die meisten Tage, die Sie nicht brauchen würden), weshalb ich vorschlage, die BufferStrategy nicht zu verwenden 'this Way, aber um physisch zwischen ihnen zu wechseln (add/remove/setVisible was auch immer) – MadProgrammer

Antwort

0

Fixed, dank MadProgrammer. Anscheinend kann eine BufferStrategy nicht zum Rendern von Swing-Komponenten verwendet werden. Ich habe gerade eine if Anweisung in Game::render() hinzugefügt, wo es nur Rendern macht, wenn der ConnectScreen nicht angezeigt wird. Wenn dies der Fall ist, wird die Arbeitsfläche nur deaktiviert und deaktiviert, während ConnectScreen::render() (umbenannt in Override JPanel::paintComponent()) nur super.paintComponent() verwendet, um Swing-Komponenten passiv zu zeichnen.