简体   繁体   中英

Java Swing MigLayout changes format on revalidate()/repaint()

So, I'm building a text-based game and have recently moved interactions from the Eclipse console to an independent window. I'm using Swing and chose the MigLayout as the most versatile layout option.

To be clear, I'm not certain it's the MigLayout specifically that's causing the problem. Basically, I have a system that allows the user to login and load a game. Before login, the window works fine and everything resizes properly. It looks like this:

原始视窗

After login, as soon as I do something to revalidate/repaint the window (changing tabs, clicking 'update'), the window changes to look like this:

修改后的窗口

and resizing stops working properly (namely, the left and right sections no longer grow and shrink horizontally).

I can't find anything in the parsing/login code that would change anything about the Swing window, so I'm not sure what's going on here.

My UI code:

import java.awt.Color;
import java.awt.Insets;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JProgressBar;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;

import net.miginfocom.swing.MigLayout;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;

import java.awt.List;
import java.awt.Font;
import javax.swing.UIManager;
import javax.swing.JPanel;
import java.awt.Dimension;

public class UserInterface {

protected JFrame frame;
protected JTextField textField;
protected JTextPane textPane;
public static List invlist;
public static List roomlist;
public JProgressBar progressBar;

/**
 * Create the application.
 */
public UserInterface() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
private void initialize() {
    frame = new JFrame();
    frame.getContentPane().setBackground(new Color(47, 79, 79));
    frame.setTitle("RAMA: a text-based single-user dungeon game");
    frame.setBounds(100, 100, 900, 325);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JMenuBar menuBar = new JMenuBar();
    frame.setJMenuBar(menuBar);

    JMenu mnNewMenu = new JMenu("Game");
    menuBar.add(mnNewMenu);

    JMenuItem mntmSave = new JMenuItem("Save");
    mnNewMenu.add(mntmSave);

    JSeparator separator = new JSeparator();
    mnNewMenu.add(separator);

    JMenuItem mntmQuit = new JMenuItem("Quit");
    mnNewMenu.add(mntmQuit);

    JMenu mnPreferences = new JMenu("Preferences");
    menuBar.add(mnPreferences);

    textField = new JTextField();
    textField.setBorder(UIManager.getBorder("CheckBoxMenuItem.border"));
    textField.setMargin(new Insets(3, 3, 3, 3));
    textField.setFont(new Font("Verdana", Font.PLAIN, 11));
    textField.setColumns(10);
    frame.getContentPane().setLayout(new MigLayout("", "[133px][3px][]0[556px,grow][163px,grow][]", "[5px][][5px][][5px][][130px,grow]0[20px,grow]"));

    JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
    frame.getContentPane().add(tabbedPane, "cell 4 0 2 7,grow");

    invlist = new List();
    invlist.setMultipleMode(true);
    tabbedPane.addTab("Inventory", null, invlist, null);
    tabbedPane.setEnabledAt(0, true);

    roomlist = new List();
    roomlist.setMultipleMode(true);
    tabbedPane.addTab("Room", null, roomlist, null);
    tabbedPane.setEnabledAt(1, true);

    progressBar = new JProgressBar();
    progressBar.setMaximum(1000);
    progressBar.setValue((int) (GameEngine.player.getStats().getNormalHunger() * 1000));
    progressBar.setStringPainted(true);
    progressBar.setForeground(new Color(233, 150, 122));
    frame.getContentPane().add(progressBar, "cell 0 1,alignx left,aligny top");

    JProgressBar progressBar_1 = new JProgressBar();
    progressBar_1.setStringPainted(true);
    progressBar_1.setForeground(new Color(95, 158, 160));
    frame.getContentPane().add(progressBar_1, "cell 0 3,growx,aligny top");

    JProgressBar progressBar_2 = new JProgressBar();
    progressBar_2.setStringPainted(true);
    progressBar_2.setForeground(new Color(144, 238, 144));
    frame.getContentPane().add(progressBar_2, "cell 0 5,growx,aligny top");

    JButton btnUpdate = new JButton("UPDATE");
    btnUpdate.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            frame.revalidate();
            frame.repaint();
        }
    });

    JScrollPane scrollPane = new JScrollPane();
    scrollPane.setBorder(UIManager.getBorder("CheckBoxMenuItem.border"));
    scrollPane.setBackground(Color.WHITE);
    scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
    scrollPane.setViewportBorder(null);
    scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    frame.getContentPane().add(scrollPane, "cell 2 0 2 7,grow");
    frame.getContentPane().add(btnUpdate, "cell 0 7,alignx center,aligny center");

    JPanel panel = new JPanel();
    panel.setBorder(null);
    panel.setMaximumSize(new Dimension(3, 19));
    panel.setPreferredSize(new Dimension(3, 19));
    panel.setMinimumSize(new Dimension(3, 19));
    panel.setBackground(new Color(255, 255, 255));
    frame.getContentPane().add(panel, "cell 2 7,alignx leading,aligny top");
    frame.getContentPane().add(textField, "cell 3 7,growx,aligny top");

    textPane = new JTextPane();
    textPane.setFont(new Font("Verdana", Font.PLAIN, 11));
    textPane.setMargin(new Insets(3, 3, 3, 0));;
    textPane.setEditable(false);
    textPane.setAutoscrolls(false);
    scrollPane.setViewportView(textPane);
}

If necessary I can include my login/load code too, but I've looked and there really isn't anything that should be modifying the layout of the window. It's just reading in some objects from a file (none of which are related to the window) and setting certain values equal to those objects.

I'm also using a couple of threads, I don't know if that would affect anything?

Let me know if there's anything else I should include here.

Fixed it, finally. Turns out it was partly to do with threads after all.
Step 1 was changing the tabLayoutPolicy of the tabbed pane from WRAP_TAB_LAYOUT to SCROLL_TAB_LAYOUT.
Step 2 was more complicated: I had implemented a system wherein each line of text submitted by the user was parsed by a newly-created thread (I suspect this was very bad design...). Something about the creation of new threads was causing the window to resize itself. So I changed my approach to use an ExecutorService:
ExecutorService parsethreads = Executors.newCachedThreadPool();
and later, inside the KeyPressed method:
parsethreads.submit(new Runnable() { public void run() { Parser.parse(line); } });
and the problem seems to have disappeared.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM