2015-11-13 4 views
0

У меня есть странная проблема с отображением компонентов в JFrame.JPanel не отображает все компоненты, изготовленные на заказ

Я должен написать свой собственный графический движок (кнопки, текстовые поля и т. Д.) Без использования Swing. Разрешено использовать только JFrame/JPanel.

Предположим, я хочу разместить 3 кнопки.

Моя кнопка Класс:

public class Button extends JPanel implements MouseListener { 

Rectangle r = new Rectangle(); 
String text; 

int X,Y,W,H; 


public Button(int x, int y, int w, int h, String t) 
{ 
    X=x; 
    Y=y; 
    W=w; 
    H=h; 

    this.setBackground(Color.CYAN); 
    addMouseListener(this); 

    r.setSize(w, h); 
    r.setLocation(x, y); 
    this.text = t; 
} 



@Override 
public void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    Graphics2D g2d = (Graphics2D)g; 
    g2d.draw(r); 
    g2d.drawString(text, X+W/2, Y+H/2); 


} 

@Override 
public void mouseClicked(MouseEvent arg0) { 
    // TODO Auto-generated method stub 

    if((arg0.getButton()==1) && r.contains(arg0.getPoint())) 
     System.out.println(arg0.getPoint().toString()); 

} 


@Override 
public void mouseEntered(MouseEvent arg0) { 
    // TODO Auto-generated method stub 

} 


@Override 
public void mouseExited(MouseEvent arg0) { 
    // TODO Auto-generated method stub 

} 


@Override 
public void mousePressed(MouseEvent arg0) { 
    // TODO Auto-generated method stub 

} 


@Override 
public void mouseReleased(MouseEvent arg0) { 
    // TODO Auto-generated method stub 

} 

} 

И в главном классе я создаю JFrame и JPanel. Я добавляю к кнопкам JPanel 3 и, наконец, JPanel для JFrame, но появляется только последняя объявленная кнопка.

public static void main(String[] args) { 
    // TODO Auto-generated method stub 


    JFrame f = new JFrame("Demo"); 
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    f.setBackground(Color.cyan); 

    JPanel j = new JPanel(new BorderLayout()); 

    j.add(new Button(10,10,100,50,"text")); 
    j.add(new Button(10,100,100,50,"text2")); 
    j.add(new Button(300,10,100,50,"text3")); 

    f.add(j); 
    f.pack(); 
    f.setSize(640, 400);; 
    f.setVisible(true); 


} 

Что я делаю неправильно?

+0

Не уверен, что вы пытаетесь сделать. Используйте компоненты или рисуйте рисунки. Если вы используете компоненты, вы можете использовать все встроенные функции Swing, такие как MouseListeners. Если вы просто рисуете рисунки, вам также необходимо реализовать все эти функции. Итак, какова цель задания? – camickr

+0

Целью этого подхода является создание графического интерфейса пользователя, который может использоваться, например, если на определенном устройстве (например, на старых мобильных телефонах) не реализовано JButton, JLabel и т. Д. – BigMacintosh

ответ

4

Ваш код не соблюдает правила BorderLayout. При добавлении 3-х компонентов в BorderLayout с использованием контейнера без указания места BorderLayout все они добавляются в пятно BorderLayout.CENTER по умолчанию, а последнее добавляется к другим. Рассмотрите возможность использования констант BorderLayout при добавлении компонентов или использовании другого менеджера компоновки).

Сказав это, я думаю, что вам лучше полностью изменить маршрут. Вместо того, чтобы рассмотреть ...

  • делает ваш класс Button логический и не GUI класса (то есть, не имея его продлить JPanel)
  • , имеющий одну одинарные JPanel без кнопок держать List<Button>,
  • имея этот единственный JPanel, нарисуйте все кнопки, перебирая список в своем методе paintComponent, вызывая метод draw(Graphics g), который имеет каждую кнопку
  • . JPanel взаимодействует с кнопками через один MouseListener.

Это значительно упростит ситуацию.

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.FontMetrics; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Rectangle; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.geom.Rectangle2D; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.*; 

public class FooGui extends JPanel { 
    private static final int PREF_W = 640; 
    private static final int PREF_H = 400; 
    private List<MyButton> btnList = new ArrayList<>(); 

    public FooGui() { 
     addMouseListener(new MyMouse()); 
    } 

    public void addButton(MyButton btn) { 
     btnList.add(btn); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     for (MyButton myButton : btnList) { 
      myButton.draw(g); 
     } 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private class MyMouse extends MouseAdapter { 
     @Override 
     public void mousePressed(MouseEvent e) { 
      for (MyButton myButton : btnList) { 
       if (myButton.getRect().contains(e.getPoint())) { 
        System.out.println("Text: " + myButton.getText()); 
       } 
      } 
     } 
    } 

    private static void createAndShowGui() { 
     FooGui fooGui = new FooGui(); 
     fooGui.addButton(new MyButton(10,10,100,50,"text")); 
     fooGui.addButton(new MyButton(10,100,100,50,"text2")); 
     fooGui.addButton(new MyButton(300,10,100,50,"text3")); 

     JFrame frame = new JFrame("FooGui"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(fooGui); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowGui(); 
      } 
     }); 
    } 
} 

class MyButton { 
    private static final Color BK = Color.CYAN; 
    private static final Color TEXT_COLOR = Color.BLACK; 
    private int x; 
    private int y; 
    private int w; 
    private int h; 
    private String text; 
    private Rectangle rect; 

    public MyButton(int x, int y, int w, int h, String t) { 
     this.x = x; 
     this.y = y; 
     this.w = w; 
     this.h = h; 
     this.text = t; 
     rect = new Rectangle(x, y, w, h); 
    } 

    public void draw(Graphics g) { 
     Graphics2D g2 = (Graphics2D) g; 
     g2.setColor(BK); 
     g2.fill(rect); 
     g2.setColor(TEXT_COLOR); 
     FontMetrics metrics = g2.getFontMetrics(); 
     Rectangle2D bounds = metrics.getStringBounds(text, g2); 
     int textX = (int) (x + (w - bounds.getWidth())/2); 
     int textY = (int) (y + (h + bounds.getHeight())/2); 

     g2.drawString(text, textX, textY); 
    } 

    public Rectangle getRect() { 
     return rect; 
    } 

    public int getX() { 
     return x; 
    } 

    public int getY() { 
     return y; 
    } 

    public int getW() { 
     return w; 
    } 

    public int getH() { 
     return h; 
    } 

    public String getText() { 
     return text; 
    } 
} 
+0

Спасибо за этот код, я только что придумал что-то в этом роде. У меня есть еще один вопрос. Почему в основном методе SwingUtilities [...] используется? – BigMacintosh

+1

@BigMacintosh [this] (http://stackoverflow.com/questions/3551542/swingutilities-invokelater-why-is-it-needed) может ответить на ваш вопрос. – Frakcool

1

Цель этого распайке заключается в создании графического интерфейса, который может быть использован, когда, например, не реализовано JButton, JLabel и т.д. в определенном устройстве (например, старые мобильные телефоны)

Ну, это на самом деле не отвечает на мой вопрос. Вы обратились к вопросу о пользовательской росписи кнопок и меток, но в GUI больше, чем просто рисовать вещи.

Я также спросил, можете ли вы использовать другие функции AWT, такие как MouseListeners, KeyListeners, tabbing, менеджеры макетов и т. Д. Поскольку, если вы можете использовать эти функции, тогда нет причин полностью изобретать колесо, как это было сделано в ответ на воздушной подушке.

Если все, что вам нужно сделать, это расширить JPanel и сделать обычную картину для кнопки или метки, тогда проблема с вашим кодом заключается в том, что вы НЕ правильно используете менеджеров компоновки. Это макет по умолчанию для рамки - BorderLayout, и вы не можете добавить несколько компонентов в CENTER of BorderLayout.

Вторая проблема с вашим размещенным кодом заключается в том, что вы не переопределяете метод ваших компонентов getPreferredSize().Поэтому размер будет равен 0, и менеджеры макетов не смогут выполнить свою работу должным образом.

Смежные вопросы