当对话框不可见时,JScrollBar setValue不起作用

时间:2014-12-05 12:21:21

标签: java swing scroll scrollbar jscrollpane

以下是我的简单示例:

import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JScrollPane;
import javax.swing.JRadioButton;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class SelectItem extends JDialog {
    private static final long serialVersionUID = 1L;
    private final JPanel contentPanel = new JPanel();
    private String item;
    private ButtonGroup group;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        final JFrame frame = new JFrame();
        frame.setBounds(100, 100, 133, 102);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new BorderLayout(0, 0));

        JButton btnSelectItem = new JButton("select item");
        btnSelectItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ArrayList<String> items = new ArrayList<String>();
                for (char c = 'A'; c <= 'Z'; c++)
                    items.add(String.valueOf(c));
                SelectItem dialog = new SelectItem(frame, items, items.get(20));

                System.out.println("Item = " + dialog.showChooseDialog());
            }
        });
        frame.getContentPane().add(btnSelectItem);
        frame.setVisible(true);
    }

    public String showChooseDialog(){
        setVisible(true);
        return item;
    }

    /**
     * Create the dialog.
     */
    public SelectItem(JFrame parent, ArrayList<String> items, String selectedItem) {
        super(parent, null, Dialog.ModalityType.DOCUMENT_MODAL);
        setTitle("Select Item");
        setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);

        setBounds(100, 100, 450, 300);
        getContentPane().setLayout(new BorderLayout());
        contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
        getContentPane().add(contentPanel, BorderLayout.CENTER);
        contentPanel.setLayout(null);

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(0, 0, 434, 228);
        contentPanel.add(scrollPane);

        JPanel panel = new JPanel();
        scrollPane.setViewportView(panel);
        panel.setLayout(null);

        int marginX = 6;
        int currentY = 7;
        int width = 420;
        int height = 23;
        int paddingY = 26;
        int scrollY = 0;
        group = new ButtonGroup();

        for (String str: items){
            JRadioButton rd = new JRadioButton(str);
            rd.setBounds(marginX, currentY, width, height);
            currentY = currentY + paddingY;
            panel.add(rd);
            group.add(rd);

            if (str == selectedItem){ //or str.equals()...
                group.setSelected(rd.getModel(), true);
                //scrollY = rd.getY() - height/2 - scrollPane.getHeight()/2;
                scrollY = rd.getY() + height/2 - scrollPane.getHeight()/2;
            }
        }
        System.out.println("ScrollY: " + scrollY);

        Dimension size = panel.getPreferredSize();
        size.setSize(size.getWidth(), currentY);
        panel.setPreferredSize(size);
        //this.setVisible(true);
        scrollPane.getVerticalScrollBar().setValue(scrollY);

        panel.repaint();
        panel.revalidate();
        scrollPane.getVerticalScrollBar().repaint();
        scrollPane.getVerticalScrollBar().revalidate();
        scrollPane.repaint();
        scrollPane.revalidate();
        this.repaint();
        this.revalidate();

        {
            JPanel buttonPane = new JPanel();
            buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
            getContentPane().add(buttonPane, BorderLayout.SOUTH);
            {
                JButton okButton = new JButton("OK");
                okButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        Enumeration<AbstractButton> iter = group.getElements();

                        while (iter.hasMoreElements()){
                            AbstractButton rd = iter.nextElement();
                            if (group.isSelected(rd.getModel())){
                                item = rd.getActionCommand();
                                break;
                            }
                        }
                        //System.out.println(group.getSelection().getActionCommand());
                        setVisible(false);
                        dispose();
                    }
                });
                okButton.setActionCommand("OK");
                buttonPane.add(okButton);
                getRootPane().setDefaultButton(okButton);
            }
            {
                JButton cancelButton = new JButton("Cancel");
                cancelButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        item = null;
                        setVisible(false);
                        dispose();
                    }
                });
                cancelButton.setActionCommand("Cancel");
                buttonPane.add(cancelButton);
            }
        }
    }
}

我创建一个String列表,然后将其传递给一个JDialog构造函数,其中包含default string valueselectedItem,如我的代码所示。
此对话框将显示列表中的所有项目,并让用户选择一个 这是通过使用JRadioButton完成的,默认情况下将选择值为default value的JRadioButton对象。
一切都很好。但我想在对话框打开时自动将面板滚动到该单选按钮,该单选按钮将位于垂直对齐的中间
像这样:
enter image description here 点。

if (str == selectedItem){ //or str.equals()...
    group.setSelected(rd.getModel(), true);
    scrollY = rd.getY() + height/2 - scrollPane.getHeight()/2;
}
...
scrollPane.getVerticalScrollBar().setValue(scrollY);

但是当对话框打开时,它不会滚动到该位置。
我知道有些东西没有更新,因为对话框不可见。
尝试添加

this.setVisible(true);

在更新滚动条之前,对话框将打开两次,第二次,它会根据需要正确显示。
但我还是不知道如何解决这个问题 任何人都可以帮助我。谢谢。 (抱歉我的语法不好)

1 个答案:

答案 0 :(得分:1)

首先:

  1. 摆脱所有repaint()和revalidate()方法。您需要使用这些方法的唯一时间是从可见GUI添加/删除组件。在这种情况下,订单是revalidate()(调用布局管理器),然后是repaint()(在新的大小/位置绘制组件)。

  2. 摆脱空布局。使用布局管理器时,滚动效果更好,每个组件确定自己的大小。

  3. 关于您的问题,在执行代码时滚动条的最大值仅为100,因此您无法将值设置为240.我猜这是因为您没有使用pack()在使对话框可见之前对话框上的方法。您应该能够在pack()之后设置滚动条的值。

    或者,更好的方法是使用panel.scrollRectToVisible(....)。即使你没有打包()对话框,这似乎也有效。