سؤال

مشكلتي الرئيسية هي الجزء التالي من التعليمات البرمجية عند إعداد ملف JFrame:

  1. لماذا لا تظهر اللوحة إذا استخدمت pack() وكيفية انجاحه؟

  2. لماذا الأول requestFocusInWindow() لا يعمل وما هو مبدأ استخدامه؟

  3. لماذا مدير التخطيط الافتراضي لـ JPanel لا يعمل إذا قمت بحذف setLayout()?


public class SoundGUI extends KeyAdapter{

public static void main(String[] args) {
    SoundGUI sGUI = new SoundGUI();
    sGUI.setUp();
}
public void setUp () {
    JFrame frame = new JFrame ("Key test");
    frame.setSize (1000, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible (true);

    Panel p = new Panel ();
    p.setLayout(new BorderLayout());//why this sentence is necessary  FlowLayout doesn't fill the container but rather lets components size to their preferredSizes.
    p.addKeyListener (this);
    p.requestFocusInWindow();//it's useless here
    //requestFocus only works on focusable components that are displayed.
    MyDrawPanel dp = new MyDrawPanel();
    dp.setBackground(Color.darkGray);

    JLabel test = new JLabel("a trial");
    JButton t = new JButton("b");
    dp.add(t);
    dp.add (test);
    p.add (dp);     
    frame.getContentPane().add(p);
    p.requestFocusInWindow();
    //frame.pack();//why it doesn't work
    //frame.setVisible(true);
}
class MyDrawPanel extends JPanel { 
    public void paintComponent (Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.setColor(Color.white);
        for (int i = 0; i < 1000; i += 42) {
            g2.fill3DRect(i,100 ,20 ,80 ,true);
        }
        g2.setColor(Color.black);
        for (int i = 21; i < 1000; i += 42) {
            g2.fill3DRect(i,100 ,20 ,80 ,true);
        }
    }
}
} 
هل كانت مفيدة؟

المحلول

اقتراحات:

  • يتصل setVisible(true) بعد الاتصال pack().من المنطقي، أليس كذلك؟
  • سيخبر BorderLayout MyDrawPanel بملء الحاوية p، حيث تتم إضافة المكون بطريقة افتراضية (أي BorderLayout.CENTER)، وهذه هي الطريقة التي يعمل بها BorderLayout.
  • لا يملأ FlowLayout الحاوية ولكنه يسمح للمكونات بالحجم حسب أحجامها المفضلة.
  • لا تخلط Swing مع مكونات AWT.أي لا تستخدم اللوحات، بل استخدم JPanels.
  • requestFocus يعمل فقط على المكونات القابلة للتركيز التي يتم عرضها.
  • من الأفضل استخدام Key Bindings بدلاً من KeyListeners.
  • من الأفضل تجنب تحديد أحجام أي شيء إن أمكن.

بناءً على الرمز الجديد، فإن مشكلتك ترجع إلى اتصالك setSize().معظم مديري التخطيط لا يحترمون هذا بل الحجم المفضل.إذا كان رسم JPanel الخاص بك يحتاج إلى أن يكون كبيرًا جدًا، فاجعله كذلك.على سبيل المثال حاول:

class MyDrawPanel extends JPanel {
  private static final int PREF_W = 1000;
  private static final int PREF_H = 300;

  public void paintComponent(Graphics g) {
     super.paintComponent(g); //!!   ******** don't forget this!!! *********
     Graphics2D g2 = (Graphics2D) g;
     g2.setColor(Color.white);
     for (int i = 0; i < 1000; i += 42) {
        g2.fill3DRect(i, 100, 20, 80, true);
     }
     g2.setColor(Color.black);
     for (int i = 21; i < 1000; i += 42) {
        g2.fill3DRect(i, 100, 20, 80, true);
     }
  }

  // the getPReferredSize will make this JPanel preferentially be this size
  @Override
  public Dimension getPreferredSize() {
     return new Dimension(PREF_W, PREF_H);
  }
}

لاحظ أيضًا أن طلب التركيز يفعل العمل إذا كان المكون قابلاً للتركيز:

  JPanel p = new JPanel(); //!! This should be a JPanel, not a Panel
  p.setFocusable(true); //!! This is needed
  p.setLayout(new BorderLayout());
  p.addKeyListener(this);
  p.requestFocusInWindow();

ولكن لاحظ أيضًا أنه يجب تجنب KeyListeners.استخدم روابط المفاتيح بدلاً من ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top