我有一个Java Swing应用程序,它有一个JScrollPane
,其中包含一些组件[多个JPanel
s]。那些JPanel
是在单击“新建” JButton
之后创建的。我的目标是使JScrollPane
滚动到下一个创建的JPanel
(即一直向下滚动)。我尝试了以下方法:
JScrollBar vertical = Scroll_Pane.getVerticalScrollBar();
vertical.setValue(vertical.getMaximum() + 40);
但是它不起作用,一旦JPanel
中至少有3个项目,最后创建的JScrollPane
总是会丢失。这是我的最小代码,如何解决?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.io.File;
import java.util.*;
import javax.swing.event.*;
public class Items_Test_Panel extends JPanel
{
public static final long serialVersionUID=26362862L;
static Dimension Screen_Size=Toolkit.getDefaultToolkit().getScreenSize();
static JFrame frame=new JFrame("Items_Test_Panel");
JScrollPane Scroll_Pane;
static int W=495,H=110,Max_H=110,Info_TextArea_H=500,Command_Info_Panel_Width=W-23,Command_Info_Panel_Height=33;
int Item_Count=0;
Color Title_Background_Color=new Color(150,206,236);
Insets An_Inset=new Insets(0,0,0,0);
JPanel Main_Panel;
static String Dir_Data="C:/Dir_Data/",Current_Item_File_Path;
static Process Child;
boolean Show_Password_B=true;
Vector<Command_Info> Command_Info_Vector;
JTextArea Info_TextArea=new JTextArea();
DocumentListener Command_Info_Field_Listener;
Swing_Robot Robot=new Swing_Robot();
ButtonGroup Item_Group=new ButtonGroup(); // Group the radio buttons.
static
{
if (!new File(Dir_Data).exists()) new File(Dir_Data).mkdirs();
}
public Items_Test_Panel(int W,int H)
{
FlowLayout Main_Panel_FL=new FlowLayout();
Main_Panel_FL.setHgap(2);
Main_Panel_FL.setVgap(2);
Max_H=H;
Command_Info_Field_Listener=new DocumentListener()
{
public void removeUpdate(DocumentEvent e) { }
public void insertUpdate(DocumentEvent e) { }
public void changedUpdate(DocumentEvent e) { }
};
Main_Panel=new JPanel(Main_Panel_FL);
Scroll_Pane=new JScrollPane(Main_Panel);
Scroll_Pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JPanel Button_Panel=new JPanel(new FlowLayout(1,36,0));
Button_Panel.setPreferredSize(new Dimension(Command_Info_Panel_Width+22,Command_Info_Panel_Height-6));
add(Button_Panel);
JButton New_Button=new JButton("New");
New_Button.setFont(new Font("Times New Roman",0,15));
New_Button.setForeground(new Color(0,28,128));
New_Button.setMargin(An_Inset);
New_Button.setPreferredSize(new Dimension(56,26));
New_Button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
Out("Command_Info_Vector.size() = "+Command_Info_Vector.size());
Create_Command_Info_Panel(++Item_Count+1,null);
revalidate();
}
});
Button_Panel.add(New_Button);
JPanel Title_Panel=new JPanel(new FlowLayout(0,1,1));
add(Title_Panel);
Title_Panel.setBorder(new EtchedBorder());
Title_Panel.setPreferredSize(new Dimension(Command_Info_Panel_Width+22,Command_Info_Panel_Height-4));
JLabel Id_Label=new JLabel(" # ");
Id_Label.setFont(new Font("Times New Roman",0,15));
Id_Label.setOpaque(true);
Id_Label.setBackground(Title_Background_Color);
Id_Label.setForeground(new Color(0,28,128));
Id_Label.setHorizontalAlignment(SwingConstants.CENTER);
Id_Label.setPreferredSize(new Dimension(69,22));
Title_Panel.add(Id_Label);
JLabel Command_Label=new JLabel("Result");
Command_Label.setFont(new Font("Times New Roman",0,15));
Command_Label.setOpaque(true);
Command_Label.setBackground(Title_Background_Color);
Command_Label.setForeground(new Color(0,28,128));
Command_Label.setHorizontalAlignment(SwingConstants.CENTER);
Command_Label.setPreferredSize(new Dimension(416,22));
Title_Panel.add(Command_Label);
add(Scroll_Pane);
JScrollPane Info_TextArea_ScrollPane=new JScrollPane(Info_TextArea);
Info_TextArea_ScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
Info_TextArea_ScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
Info_TextArea_ScrollPane.setPreferredSize(new Dimension(W-2,Info_TextArea_H));
add(Info_TextArea_ScrollPane);
Load_Data("");
}
void Create_Command_Info_Panel(int Id,final Command_Info A_Command_Info)
{
FlowLayout Panel_FL=new FlowLayout();
Panel_FL.setHgap(1);
Panel_FL.setVgap(1);
JPanel Command_Info_Panel=new JPanel(Panel_FL);
Command_Info_Panel.setBorder(new EtchedBorder());
Command_Info_Panel.setPreferredSize(new Dimension(Command_Info_Panel_Width,Command_Info_Panel_Height));
JRadioButton Id_Button=new JRadioButton("[ "+(Id==-1?Item_Count+1:Id)+" ]");
Id_Button.setFont(new Font("Times New Roman",0,15));
Id_Button.setForeground(new Color(0,28,128));
Id_Button.setPreferredSize(new Dimension(65,26));
Item_Group.add(Id_Button);
Id_Button.setSelected(true);
Command_Info_Panel.add(Id_Button);
JTextField Result_Field=new JTextField(A_Command_Info==null?"":A_Command_Info.Result);
Result_Field.setPreferredSize(new Dimension(398,27));
Result_Field.getDocument().addDocumentListener(Command_Info_Field_Listener);
Command_Info_Panel.add(Result_Field);
Main_Panel.add(Command_Info_Panel);
if (A_Command_Info==null) Command_Info_Vector.add(new Command_Info("[ "+(Item_Count)+" ]","","",""));
Update_Layout();
}
void Load_Data(String Items_Dir)
{
Command_Info A_Command_Info=null;
Main_Panel.removeAll();
Item_Count=0;
Info_TextArea.setText("");
Command_Info_Vector=new Vector();
if (Command_Info_Vector.size()>0)
{
Item_Count=Command_Info_Vector.size();
for (int i=0;i<Command_Info_Vector.size();i++)
{
A_Command_Info=Command_Info_Vector.elementAt(i);
Create_Command_Info_Panel(i+1,A_Command_Info);
}
Item_Count--;
Info_TextArea.setText(A_Command_Info.Info);
}
else Create_Command_Info_Panel(-1,null);
Update_Layout();
}
void Update_Layout()
{
Main_Panel.setPreferredSize(new Dimension(Command_Info_Panel_Width,Item_Count*(Command_Info_Panel_Height+2)+36));
if (Item_Count*(Command_Info_Panel_Height+2)+40<Max_H) Scroll_Pane.setPreferredSize(new Dimension(W-2,Item_Count*(Command_Info_Panel_Height+2)+40));
else Scroll_Pane.setPreferredSize(new Dimension(W-2,Max_H));
Scroll_Pane.revalidate();
Scroll_Pane.repaint();
revalidate();
repaint();
JScrollBar vertical=Scroll_Pane.getVerticalScrollBar();
vertical.setValue(vertical.getMaximum()+40);
Out(" vertical.getMaximum() = "+vertical.getMaximum()+" vertical.getMinimum() = "+vertical.getMinimum());
/*
Online advice of how to adjudt the Scroll_Pane : https://robbamforth.wordpress.com/2015/06/24/java-how-to-scroll-to-a-particular-component-in-jscrollpane-and-gain-focus/
JPanel comp=(JPanel)Main_Panel.getComponent(Main_Panel.getComponentCount()-1);
// vertical.setValue(Main_Panel.getParent().getLocation().y+(Main_Panel.getLocation().y+50));
// JComponent comp=Main_Panel;
// vertical.setValue(comp.getParent().getLocation().y+(comp.getLocation().y+50));
vertical.setValue(250);
comp.requestFocus();
Out(comp.toString());
vertical.repaint();
vertical.revalidate();
*/
if (Item_Count*(Command_Info_Panel_Height+2)+40<Max_H) frame.setPreferredSize(new Dimension(W+17,Item_Count*(Command_Info_Panel_Height+2)+122+Command_Info_Panel_Height+Info_TextArea_H));
else frame.setPreferredSize(new Dimension(W+17,Max_H+82+Command_Info_Panel_Height+Info_TextArea_H));
frame.pack();
frame.revalidate();
frame.repaint();
}
private static void out(String message) { System.out.print(message); }
private static void Out(String message) { System.out.println(message); }
// Create the GUI and show it. For thread safety, this method should be invoked from the event-dispatching thread.
static void Create_And_Show_GUI()
{
final Items_Test_Panel demo=new Items_Test_Panel(W,H);
frame.add(demo);
frame.addWindowListener( new WindowAdapter()
{
public void windowActivated(WindowEvent e) { }
public void windowClosed(WindowEvent e) { }
public void windowClosing(WindowEvent e)
{
System.exit(0);
Child.destroy();
}
public void windowDeactivated(WindowEvent e) { }
public void windowDeiconified(WindowEvent e) { demo.repaint(); }
public void windowGainedFocus(WindowEvent e) { demo.repaint(); }
public void windowIconified(WindowEvent e) { }
public void windowLostFocus(WindowEvent e) { }
public void windowOpening(WindowEvent e) { demo.repaint(); }
public void windowOpened(WindowEvent e) { }
public void windowResized(WindowEvent e) { demo.repaint(); }
public void windowStateChanged(WindowEvent e) { demo.repaint(); }
});
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args)
{
// Schedule a job for the event-dispatching thread : creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() { public void run() { Create_And_Show_GUI(); } });
}
}
class Command_Info
{
String Id,Date,Result,Info;
Command_Info(String Id,String Date,String Result,String Info)
{
this.Id=Id;
this.Date=Date;
this.Result=Result;
this.Info=Info;
}
public String toString() { return "Id = "+Id+" Date = [ "+Date+" ] Result = [ "+Result+" ] Info = [ "+Info+" ]"; }
}
答案 0 :(得分:1)
您正在分配和更新JScrollBar
,然后再对其进行更新。这就是为什么您落后一步(最新的JRadioButton
和JTextField
未显示)的原因。解决方法是先通过frame.pack();
更新组件,然后使用vertical.setValue(...);
设置值。将您的void Update_Layout() {...}
更改为以下内容:
void Update_Layout() {
Main_Panel.setPreferredSize(new Dimension(Command_Info_Panel_Width, Item_Count * (Command_Info_Panel_Height + 2) + 36));
if (Item_Count * (Command_Info_Panel_Height + 2) + 40 < Max_H) {
Scroll_Pane.setPreferredSize(new Dimension(W - 2, Item_Count * (Command_Info_Panel_Height + 2) + 40));
} else {
Scroll_Pane.setPreferredSize(new Dimension(W - 2, Max_H));
}
Scroll_Pane.revalidate();
Scroll_Pane.repaint();
revalidate();
repaint();
Main_Panel.revalidate();
Main_Panel.repaint();
/*
Online advice of how to adjudt the Scroll_Pane : https://robbamforth.wordpress.com/2015/06/24/java-how-to-scroll-to-a-particular-component-in-jscrollpane-and-gain-focus/
JPanel comp=(JPanel)Main_Panel.getComponent(Main_Panel.getComponentCount()-1);
// vertical.setValue(Main_Panel.getParent().getLocation().y+(Main_Panel.getLocation().y+50));
// JComponent comp=Main_Panel;
// vertical.setValue(comp.getParent().getLocation().y+(comp.getLocation().y+50));
vertical.setValue(250);
comp.requestFocus();
Out(comp.toString());
vertical.repaint();
vertical.revalidate();
*/
if (Item_Count * (Command_Info_Panel_Height + 2) + 40 < Max_H) {
frame.setPreferredSize(new Dimension(W + 17, Item_Count * (Command_Info_Panel_Height + 2) + 122 + Command_Info_Panel_Height + Info_TextArea_H));
} else {
frame.setPreferredSize(new Dimension(W + 17, Max_H + 82 + Command_Info_Panel_Height + Info_TextArea_H));
}
//HERE!
frame.pack();
JScrollBar vertical = Scroll_Pane.getVerticalScrollBar();
vertical.setValue(vertical.getMaximum());
Out(" vertical.getMaximum() = " + vertical.getMaximum() + " vertical.getMinimum() = " + vertical.getMinimum());
//frame.pack();//in case you want to pack again, not needed for your fix.
frame.revalidate();
frame.repaint();
}