问题:使用 JOptionPane 会阻止我的 JPanel 切换
Problem: The use of JOptionPane stops my JPanels from switching
所以这段代码的目的是使用 JOptionPane 获取用户输入,验证它,确保输入是“Hello World”,如果是,从红色的 JPanel 切换到空白的顶部的 JLabel Hello World。但是,当在 JPanel 的文本字段中键入“Hello World”并单击“确定”时,红色的 JPanel 将被删除,但带有 JLabel 的空白面板不会出现。我使用 isDisplayable() 方法检查是否显示了带有 JLabel 的空白 JPanel,结果为真。我不确定问题是什么或如何解决。这是我的代码:
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.lang.*;
import javax.sound.sampled.Line;
import javax.swing.*;
import javax.swing.Timer;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.*;
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
public class Main {
private static JFrame frame = new JFrame();
private static JPanel colorPanel = new JPanel();
private static JPanel testPanel = new JPanel();
private static JLabel testLabel = new JLabel("Hello World");
public static void main(String[] args) {
frame.setSize(500, 500);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setResizable(false);
colorPanel.setBackground(Color.RED);
frame.add(colorPanel);
frame.setVisible(true);
String input = JOptionPane.showInputDialog("Enter");
if(input.equals("Hello World"))
{
frame.remove(colorPanel);
frame.validate();
frame.repaint();
testPanel.add(testLabel);
frame.add(testPanel);
}
}
}
frame.validate()
应该是 frame.revalidate()
并且应该在所有组件 adds/removes"
之后发生
if(input.equals("Hello World"))
{
frame.remove(colorPanel);
testPanel.add(testLabel);
frame.add(testPanel);
frame.revalidate();
}
我知道你已经接受了答案,但我不得不插嘴,因为我觉得虽然答案在技术上是正确的,但它可能不是最好的解决方案。
请注意,首先,您的问题与 .validate()
和 .revalidate()
关系不大,而与您调用它的位置有关。必须在完成所有更改后调用它,这意味着在删除所有组件并添加之后。
另请注意,通常最好在您的容器上安装 repaint()
并在 调用 revalidate()
之后调用它 ,尤其是在您删除组件时,因为这会帮助清除 GUI 中任何潜在的“脏”像素。
现在开始我的回答:最好不要推出您自己的解决方案,而是使用您的 GUI 库为您提供的更高级别的工具,这里是 CardLayout(教程:CardLayout Tutorial)。使用此工具,您可以轻松地向前或向后滚动“卡片”组件,这里是使用 .previous(...)
和 .next(...)
方法的 JPanel,或者通过调用 .show(...)
以灵活的方式交换组件方法。该布局还将调整使用该布局并容纳“卡片”组件的容器的大小,以便保证所有卡片都适合。
.next(...)
、.previous(...)
和 .show(...)
的使用示例可以在下面的可编译和可运行代码中看到。另外,请看看评论:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import javax.swing.*;
public class SwapPanels extends JPanel {
private static final long serialVersionUID = 1L;
private CardLayout cardLayout = new CardLayout(); // the layout
private JPanel cardHolderPanel = new JPanel(cardLayout); // the JPanel that holds the cards
// a combo box and model for allowing random-access swapping
private DefaultComboBoxModel<String> comboModel = new DefaultComboBoxModel<>();
private JComboBox<String> swapPanelCombo = new JComboBox<>(comboModel);
public SwapPanels() {
// listener added to combobox to allow swapping of panels
swapPanelCombo.addActionListener(e -> swapPanel());
JButton previousBtn = new JButton("Previous");
previousBtn.addActionListener(e -> cardLayout.previous(cardHolderPanel));
JButton nextBtn = new JButton("Next");
nextBtn.addActionListener(e -> cardLayout.next(cardHolderPanel));
// panel to hold buttons and combo box
JPanel controlPanel = new JPanel();
controlPanel.add(previousBtn);
controlPanel.add(nextBtn);
controlPanel.add(swapPanelCombo);
// create and add our "card" JPanels, showing different colors
addColorPanel("White", Color.WHITE);
addColorPanel("Red", Color.RED);
addColorPanel("Orange", Color.ORANGE);
addColorPanel("Yellow", Color.YELLOW);
addColorPanel("Green", Color.GREEN);
addColorPanel("Blue", Color.BLUE);
addColorPanel("Cyan", Color.CYAN);
// add components to the main *this* JPanel
setPreferredSize(new Dimension(600, 450));
setLayout(new BorderLayout());
add(cardHolderPanel);
add(controlPanel, BorderLayout.PAGE_END);
}
private void addColorPanel(String text, Color color) {
// create color JPanel
JPanel colorPanel = new JPanel();
colorPanel.setBackground(color);
// label to display color name
JLabel label = new JLabel(text, SwingConstants.CENTER);
// make label big
label.setFont(label.getFont().deriveFont(Font.BOLD, 24f));
// place label in the center of the color JPanel
colorPanel.setLayout(new GridBagLayout());
colorPanel.add(label);
// add text to your jcombo box as well
comboModel.addElement(text);
// add color panel to the card-holder JPanel
cardHolderPanel.add(colorPanel, text);
}
private void swapPanel() {
// get combo box's text
String text = (String) swapPanelCombo.getSelectedItem();
if (text != null) {
// use the text to swap jpanels
cardLayout.show(cardHolderPanel, text);
}
}
// be sure to show our GUI on the Swing event thread
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
SwapPanels mainPanel = new SwapPanels();
JFrame frame = new JFrame("Swap Panels");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
所以这段代码的目的是使用 JOptionPane 获取用户输入,验证它,确保输入是“Hello World”,如果是,从红色的 JPanel 切换到空白的顶部的 JLabel Hello World。但是,当在 JPanel 的文本字段中键入“Hello World”并单击“确定”时,红色的 JPanel 将被删除,但带有 JLabel 的空白面板不会出现。我使用 isDisplayable() 方法检查是否显示了带有 JLabel 的空白 JPanel,结果为真。我不确定问题是什么或如何解决。这是我的代码:
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.lang.*;
import javax.sound.sampled.Line;
import javax.swing.*;
import javax.swing.Timer;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.*;
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
public class Main {
private static JFrame frame = new JFrame();
private static JPanel colorPanel = new JPanel();
private static JPanel testPanel = new JPanel();
private static JLabel testLabel = new JLabel("Hello World");
public static void main(String[] args) {
frame.setSize(500, 500);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setResizable(false);
colorPanel.setBackground(Color.RED);
frame.add(colorPanel);
frame.setVisible(true);
String input = JOptionPane.showInputDialog("Enter");
if(input.equals("Hello World"))
{
frame.remove(colorPanel);
frame.validate();
frame.repaint();
testPanel.add(testLabel);
frame.add(testPanel);
}
}
}
frame.validate()
应该是 frame.revalidate()
并且应该在所有组件 adds/removes"
if(input.equals("Hello World"))
{
frame.remove(colorPanel);
testPanel.add(testLabel);
frame.add(testPanel);
frame.revalidate();
}
我知道你已经接受了答案,但我不得不插嘴,因为我觉得虽然答案在技术上是正确的,但它可能不是最好的解决方案。
请注意,首先,您的问题与 .validate()
和 .revalidate()
关系不大,而与您调用它的位置有关。必须在完成所有更改后调用它,这意味着在删除所有组件并添加之后。
另请注意,通常最好在您的容器上安装 repaint()
并在 调用 revalidate()
之后调用它 ,尤其是在您删除组件时,因为这会帮助清除 GUI 中任何潜在的“脏”像素。
现在开始我的回答:最好不要推出您自己的解决方案,而是使用您的 GUI 库为您提供的更高级别的工具,这里是 CardLayout(教程:CardLayout Tutorial)。使用此工具,您可以轻松地向前或向后滚动“卡片”组件,这里是使用 .previous(...)
和 .next(...)
方法的 JPanel,或者通过调用 .show(...)
以灵活的方式交换组件方法。该布局还将调整使用该布局并容纳“卡片”组件的容器的大小,以便保证所有卡片都适合。
.next(...)
、.previous(...)
和 .show(...)
的使用示例可以在下面的可编译和可运行代码中看到。另外,请看看评论:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import javax.swing.*;
public class SwapPanels extends JPanel {
private static final long serialVersionUID = 1L;
private CardLayout cardLayout = new CardLayout(); // the layout
private JPanel cardHolderPanel = new JPanel(cardLayout); // the JPanel that holds the cards
// a combo box and model for allowing random-access swapping
private DefaultComboBoxModel<String> comboModel = new DefaultComboBoxModel<>();
private JComboBox<String> swapPanelCombo = new JComboBox<>(comboModel);
public SwapPanels() {
// listener added to combobox to allow swapping of panels
swapPanelCombo.addActionListener(e -> swapPanel());
JButton previousBtn = new JButton("Previous");
previousBtn.addActionListener(e -> cardLayout.previous(cardHolderPanel));
JButton nextBtn = new JButton("Next");
nextBtn.addActionListener(e -> cardLayout.next(cardHolderPanel));
// panel to hold buttons and combo box
JPanel controlPanel = new JPanel();
controlPanel.add(previousBtn);
controlPanel.add(nextBtn);
controlPanel.add(swapPanelCombo);
// create and add our "card" JPanels, showing different colors
addColorPanel("White", Color.WHITE);
addColorPanel("Red", Color.RED);
addColorPanel("Orange", Color.ORANGE);
addColorPanel("Yellow", Color.YELLOW);
addColorPanel("Green", Color.GREEN);
addColorPanel("Blue", Color.BLUE);
addColorPanel("Cyan", Color.CYAN);
// add components to the main *this* JPanel
setPreferredSize(new Dimension(600, 450));
setLayout(new BorderLayout());
add(cardHolderPanel);
add(controlPanel, BorderLayout.PAGE_END);
}
private void addColorPanel(String text, Color color) {
// create color JPanel
JPanel colorPanel = new JPanel();
colorPanel.setBackground(color);
// label to display color name
JLabel label = new JLabel(text, SwingConstants.CENTER);
// make label big
label.setFont(label.getFont().deriveFont(Font.BOLD, 24f));
// place label in the center of the color JPanel
colorPanel.setLayout(new GridBagLayout());
colorPanel.add(label);
// add text to your jcombo box as well
comboModel.addElement(text);
// add color panel to the card-holder JPanel
cardHolderPanel.add(colorPanel, text);
}
private void swapPanel() {
// get combo box's text
String text = (String) swapPanelCombo.getSelectedItem();
if (text != null) {
// use the text to swap jpanels
cardLayout.show(cardHolderPanel, text);
}
}
// be sure to show our GUI on the Swing event thread
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
SwapPanels mainPanel = new SwapPanels();
JFrame frame = new JFrame("Swap Panels");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}