【问题标题】:repaint from JComboBox control从 JComboBox 控件重绘
【发布时间】:2012-03-06 07:15:31
【问题描述】:

当用户选择 JComboBox 中的各种选项时,我试图让绘制的图形刷新/重新填充。我在网上找到的示例都使用了 JLabels,这对于图像文件可能很好,但不适用于 paintComponent 生成的自定义图形。

我尝试在下面大约 60 行代码中推出自己的解决方案。我正在使用要重新调整大小的矩形的一个简单示例。如果您编译并运行下面的代码,您将看到当用户从 JComboBox 中选择不同的选项时它不会重新绘制。此外,我还故意没有对 displayConstraints 做任何事情,因为如果有人有更好的方法,我不想强​​加解决方案。我的目标是让 JComboBox 显示在其自己的顶部行中,并在第一行下方更大的第二行中完成绘图。第二行将吸收所有调整大小的变化,而当 JFrame 调整大小时,第一行将保持或多或少相同的大小。通过从 JComboBox 中选择不同的选项,用户将能够使绘制的矩形相对于 JFrame 的当前大小变得更小或更大。

谁能告诉我如何修复下面的代码以实现我的上述目标?

import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;

public class ComboBox extends JFrame implements ItemListener {
final String[] sizes = { "10%", "20%", "33%" };
JComboBox combobox = new JComboBox(sizes);
int selectedIndex;

public ComboBox() {
    setLayout(new GridBagLayout());
    combobox.setSelectedIndex(-1);
    combobox.addItemListener(this);
    GridBagConstraints comboBoxConstraints = new GridBagConstraints();
    comboBoxConstraints.gridx = 0;
    comboBoxConstraints.gridy = 0;
    comboBoxConstraints.gridwidth = 1;
    comboBoxConstraints.gridheight = 1;
    comboBoxConstraints.fill = GridBagConstraints.NONE;
    add(combobox,comboBoxConstraints);//This should be placed at top, in middle.

    GridBagConstraints displayConstraints = new GridBagConstraints();
    displayConstraints.gridx = 0;
    displayConstraints.gridy = 1;
    displayConstraints.gridwidth = 1;
    displayConstraints.gridheight = 1;
    displayConstraints.fill = GridBagConstraints.BOTH;
    //I am aware that nothing is done with displayConstraints.
    //I just want to indicate that the rectangle should go below the combobox,
    //and that the rectangle should resize while the combobox should not.
    //Other suggested approaches are welcome.

    setSize(300, 300);
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    setLocationRelativeTo(null);
    setVisible(true);
}

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

public void itemStateChanged(ItemEvent e) {
    if (e.getStateChange() == ItemEvent.SELECTED) {
        JComboBox combo = (JComboBox) e.getSource();
        selectedIndex = combo.getSelectedIndex();
        System.out.println("selectedIndex is: "+selectedIndex);
        repaint();
    }
}
protected void paintComponent(Graphics g){
    int scaleFactor = 1;
    if(selectedIndex==0){scaleFactor = 10;}
    if(selectedIndex==1){scaleFactor = 5;}
    if(selectedIndex==2){scaleFactor = 3;}
    if(selectedIndex!=-1){
        int xStart = (getWidth()/2)-(getWidth()/scaleFactor);
        int yStart = (getHeight()/2)-(getHeight()/scaleFactor);
        g.drawRect(xStart, yStart, (getWidth()/scaleFactor), (getHeight()/scaleFactor));
    }
}
}

【问题讨论】:

  • 问题在编辑之前很好
  • 您可以恢复编辑,但现在看起来可以了。

标签: java swing graphics plot jcombobox


【解决方案1】:

你不应该直接在 JFrame 中绘制,即使你这样做了,JFrame 也没有 paintComponent 方法。使用@Override 注释自己查看。相反,在 JPanel 或 JComponent 中进行绘制,在paintComponent 中进行绘制,并确保您使用 override 注释正确地覆盖了该方法。

例如:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ComboBoxTest extends JPanel implements ItemListener {
   private static final int PREF_W = 300;
   private static final int PREF_H = PREF_W;
   final String[] sizes = { "10%", "20%", "33%" };
   JComboBox combobox = new JComboBox(sizes);
   int selectedIndex;
   private double scaleFactor = 1;

   public ComboBoxTest() {
      setLayout(new GridBagLayout());
      combobox.setSelectedIndex(-1);
      combobox.addItemListener(this);
      GridBagConstraints comboBoxConstraints = new GridBagConstraints();
      comboBoxConstraints.gridx = 0;
      comboBoxConstraints.gridy = 0;
      comboBoxConstraints.gridwidth = 1;
      comboBoxConstraints.gridheight = 1;
      comboBoxConstraints.fill = GridBagConstraints.NONE;
      add(combobox, comboBoxConstraints);// This should be placed at top, in
                                         // middle.

      GridBagConstraints displayConstraints = new GridBagConstraints();
      displayConstraints.gridx = 0;
      displayConstraints.gridy = 1;
      displayConstraints.gridwidth = 1;
      displayConstraints.gridheight = 1;
      displayConstraints.fill = GridBagConstraints.BOTH;
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   public void itemStateChanged(ItemEvent e) {
      if (e.getStateChange() == ItemEvent.SELECTED) {
         JComboBox combo = (JComboBox) e.getSource();
         selectedIndex = combo.getSelectedIndex();
         System.out.println("selectedIndex is: " + selectedIndex);
         if (selectedIndex == -1) {
            return;
         }
         String selectedItem = combo.getSelectedItem().toString().trim();
         selectedItem = selectedItem.replace("%", "");
         scaleFactor = Double.parseDouble(selectedItem) / 100.0;
         repaint();
      }
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
         int xStart = (getWidth() / 2) - (int)(getWidth() * scaleFactor);
         int yStart = (getHeight() / 2) - (int)(getHeight() * scaleFactor);
         g.drawRect(xStart, yStart, (int)(getWidth() * scaleFactor),
               (int)(getHeight() * scaleFactor));
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("ComboBoxTest");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new ComboBoxTest());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

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

【讨论】:

  • +1 快速回复。我将此标记为答案,但它仍然将组合框放在框架的中间而不是顶部。当我有更多时间时,我会尝试修复这个细节。
  • @CodeMed:要将其放在顶部,请使用不同的布局管理器。我自己我会使用 JPanel 将 JComboBox 放在 FlowLayout 中,然后将该 JPanel 放在另一个使用 BorderLayout 的 JPanel(主面板)的 BorderLayout.NORTH 位置。
【解决方案2】:

在我的脑海中,没有测试这是我想出的。创建一个子类JPanel 覆盖paintComponent 你在哪里做你的图形(就像Hovercraft Full Of Eels 所说的那样)。添加到 JFrame。现在将ActionListener(而不是ItemListener)添加到您的组合框:

public void actionPerformed(ActionEvent evt) {
    //do other stuff...
    yourGraphicsPanel.repaint();
}

yourGraphicsPanel 是 JPanel 子类的一个实例。

希望对您有所帮助! :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    相关资源
    最近更新 更多