简体   繁体   English

Java Swing MigLayout在revalidate()/ repaint()上更改格式

[英]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. 因此,我正在构建一个基于文本的游戏,并且最近将交互从Eclipse控制台移到了一个独立的窗口。 I'm using Swing and chose the MigLayout as the most versatile layout option. 我正在使用Swing,并选择了MigLayout作为最通用的布局选项。

To be clear, I'm not certain it's the MigLayout specifically that's causing the problem. 需要明确的是,我不确定是MigLayout引起了该问题。 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. 我在解析/登录代码中找不到任何可以改变有关Swing窗口的内容,因此我不确定这里发生了什么。

My UI code: 我的UI代码:

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. 步骤1是将选项卡式窗格的tabLayoutPolicy从WRAP_TAB_LAYOUT更改为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...). 步骤2更加复杂:我已经实现了一个系统,其中用户提交的每一行文本都由一个新创建的线程来解析(我怀疑这是非常糟糕的设计...)。 Something about the creation of new threads was causing the window to resize itself. 关于创建新线程的某种事情正在导致窗口调整自身大小。 So I changed my approach to use an ExecutorService: 因此,我更改了使用ExecutorService的方法:
ExecutorService parsethreads = Executors.newCachedThreadPool();
and later, inside the KeyPressed method: 然后在KeyPressed方法内:
parsethreads.submit(new Runnable() { public void run() { Parser.parse(line); } });
and the problem seems to have disappeared. 而且问题似乎已经消失了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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