2016-04-05 16 views
2

Arka plan resmimi bu çerçevede en alttaki ve en üstteki düğüme koymak istiyorum. Ancak aşağıda yazdığım kod çalışmıyor. Sorunların nerede olduğunu bilen var mı?Arka plan resmimi en altta nasıl belirleyeceğim

Başka bir şey, düğmeme ait yeri ayarladığım halde, çerçevenin üst orta noktasında gösterilmemedir.

Lütfen yorum satırlarını dikkate almayın. (Sadece tahmin ve onlara çalışacak umuduyla, ancak görünüşe göre değil edilmiştir.)

public class Menu extends JFrame{ 
private JLayeredPane pane; 
private JLayeredPane pane2; 

public Menu(){ 
    final JFrame f = new JFrame("Chinese Chess"); 


    JButton play = new JButton("Play vs. AI"); 

    f.setLayout(new FlowLayout()); 
    f.setLocationRelativeTo(null); 
    f.setSize(800, 800); 
    f.setVisible(true); 
    f.setResizable(false); 
    //f.pack(); 

    pane = new JLayeredPane(); 
    pane2 = new JLayeredPane(); 
    f.add(pane); 
    f.add(pane2); 


    //background image 
    JLabel background = new JLabel(new ImageIcon("res/img/background.png")); 
    background.setLocation(0, 0); 
    background.setSize(800, 800); 
    pane.add(background, JLayeredPane.FRAME_CONTENT_LAYER); 
    pane2.add(play, JLayeredPane.DEFAULT_LAYER); 
    //pane.moveToBack(); 

    //button PlayAI 
    play.setLocation(500,500); 
    play.setPreferredSize(new Dimension(100,50)); 
    //f.setLayout(new FlowLayout()); 

    //frame menu 
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    //f.getContentPane().add(play); 


    play.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent ae) { 
      new PlayAI(); 
     } 
    }); 
} 

public static void main(String[] args){ 
    new Menu(); 
} 

cevap

5

Sorunlar/Çözümler: aramaların

  • setLocation(...) ve setBounds(...) türleri Birçok düzen yöneticileri tarafından göz ardı edilir. Bunları kullanmanın tek yolu, kapsayıcının düzenini sıfır olarak .setLayout(null);
  • üzerinden ayarlamaktır. Ancak, boş düzenler ve setBounds(), yeni GUI'leri karmaşık GUI'leri oluşturmanın en kolay ve en iyi yolu gibi Swing yaparken daha fazla Swing'e sahip olabilir. GUI, bunları kullanırken karşılaşacağınız daha ciddi zorlukları yaratıyorsunuz. GUI yeniden boyutlandırıldığında bileşenlerinizi yeniden boyutlandırmazlar, geliştirmek veya sürdürmek için bir kraliyet cadısıdırlar, kaydırma yuvalarına yerleştirildiğinde tamamen başarısız olurlar, orijinal platformdan farklı olan tüm platformlarda veya ekran çözünürlüklerinde görüntülendiklerinde çok kötü görünürler. .
  • Özetle - bunu yapma, boş olmayan düzenleri veya setBounds kullanma, her biri kendi düzen yöneticisini kullanan JPanels'ı yuvalama ve böylece bakımı kolay ve düzgün GUI'leri oluşturma.
  • Bir görüntünün arka planda olmasını istiyorsanız, o zaman bu sitede birçok benzer soruda gösterildiği gibi JPA'nın paintComponent(Graphics g) yönteminde çizerek GUI bileşenleriniz için kapsayıcı olarak kullandığınız bir JPanel'e çizin. - Bir kaç saniyede seni bulurum.
  • Bu resimdeki JPanel çiziminin üstüne herhangi bir JPanel eklerseniz, bu JPanels öğesinin üstündeki setOpaque(false) numaralı telefonu arayarak bunları görebildiğinizden emin olun. Aksi takdirde görüntüyü kapatacaksınız.
  • Yalnızca bir tane gerektiğinde kodunuzun iki JFram'ı vardır. Kullanmadığınızdan kurtulun.
  • Bileşenler GUI - yok'a eklenmeden önce JFrame'de çok erken setVisible(true) numaralı telefonu arayın. Her şeyi yalnızca GUI'ye ekledikten sonra çağırın, böylece tüm ekranlar TAMAM.
  • İki JLayedPanes oluşturuyorsunuz ve JFrame'in BorderLayout ek bileşenlerini nasıl işlediğini anlamadan JFrame'e ekleyerek tamamen diğerini kaplıyorsunuz.
  • Bir JLayeredPane kullanmamanızı öneririm, ancak yukarıda belirtildiği gibi JPanel'de çizin ve bunu kapsayıcınız olarak kullanın.
  • Kodunuz, oynatma düğmesine basıldığında tamamen yeni bir GUI penceresi açıyor gibi görünüyor ve eğer öyleyse, bu kullanıcı için can sıkıcı olabilir. Görünümleri bir CardLayout ile değiştirmeyi düşünün. Örneğin

:

Yukarıda çözeltisinden
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 

import javax.imageio.ImageIO; 
import javax.swing.*; 

// extend JPanel so you can draw to its background 
@SuppressWarnings("serial") 
public class Menu2 extends JPanel { 
    private BufferedImage bgImage = null; // our background image 
    private JButton playButton = new JButton(new PlayVsAiAction("Play Vs. AI", KeyEvent.VK_P)); 

    public Menu2(BufferedImage bgImage) { 
     this.bgImage = bgImage; 

     setLayout(new GridBagLayout()); // center our button 
     add(playButton); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if (bgImage != null) { 
      g.drawImage(bgImage, 0, 0, this); 
     } 
    } 

    // to size our GUI to match a constant or the image. 
    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
      return super.getPreferredSize(); 
     } 

     // if you want to size it based on the image 
     if (bgImage != null) { 
      int width = bgImage.getWidth(); 
      int height = bgImage.getHeight(); 
      return new Dimension(width, height);    
     } else { 
      return super.getPreferredSize(); 
     } 

     // if you want to size the GUI with constants: 
     // return new Dimension(PREF_W, PREF_H); 
    } 

    private class PlayVsAiAction extends AbstractAction { 
     public PlayVsAiAction(String name, int mnemonic) { 
      super(name); // have our button display this name 
      putValue(MNEMONIC_KEY, mnemonic); // alt-key to press button 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      // TODO code to start program 

     } 
    } 

    private static void createAndShowGui() { 
     BufferedImage img = null; 
     String imagePath = "res/img/background.png"; 
     try { 
      // TODO: fix this -- use class resources to get image, not File 
      img = ImageIO.read(new File(imagePath)); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.exit(-1); 
     } 
     Menu2 mainPanel = new Menu2(img); 

     JFrame frame = new JFrame("Chinese Chess"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> { 
      createAndShowGui(); 
     }); 
    } 
} 
+0

Çok teşekkürler! Açıklamalarla gerçekten yardımcı oluyor. Lütfen kodumu değiştirmek için biraz zaman verin ve size daha sonra bazı geri bildirimler vereceğ[email protected] –

+0

neden bgImage = null ayarlıyorsunuz? @HovercraftFullOfEels –

+0

@AnthonyZhang: değişkeni bildirdiğim bgImage'a BufferedImage atamam çünkü - imkansız olamam. Bunun yerine kurucuya atayım (açıkça görebildiğiniz gibi). –

2

... oluşturmak ve salıncak uygulama bu şekilde başlatması gerektiğini:

public static void main(String[] args) { 
    //Schedule a job for the event-dispatching thread: 
    //creating and showing this application's GUI. 
    javax.swing.SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGUI(); 
     } 
    }); 
} 

private static void createAndShowGUI() { 
    // Instantiate your JFrame and show it 
} 
+0

Teşekkürler;) @HovercraftFullOfEels – Jorge

+0

Teşekkürler! Ben aslında java'da bir acemiim. Her iki kodunuzda anlamadığım bir satır "SwingUtilities.invokeLater (yeni Runnable())" dır. Bana ne yaptığını söyleyebilir misin? @Jorge –

+0

@AnthonyZhang Bunun kısa bir özgeçmiş olduğunu göz önünde bulundurun !!! Umut ediyorum bu yardım eder. Salınımla çalışma, kullanıcı arabirimindeki tüm güncelleştirmeler olay dağıtım iş parçacığı (AWT Event Dispatch Thread) üzerinde gerçekleşmelidir. Yani, GUI için bir güncellemeyi ima eden herhangi bir yönteme yapılan herhangi bir çağrı, bu Konudan çağrılmalıdır. InvokeLater kullanarak kodunuzun EDT'de yürütüleceğini garanti eder. Diğer seçenekler (invokeAndWait gibi) vardır, ancak bu durum özellikle kodunuzu mümkün olan en kısa sürede EDT'de yürütecektir (diğer tüm önceki olaylar işlendikten sonra). – Jorge