I have some code that get's data from a h2 dB and then displays it in a JScrollPane. I have added a button that should refresh the information but it isn't working.
This is my code:
Code that is used for the JPanel:
JPanel pList = new JPanel();
Component pListl = new JLabel("Here you can view players. Searching and more data will be coming soon.");
pList.add(pListl,SwingConstants.CENTER);
tabbedPane.addTab("Player List",pList);
tabbedPane.setMnemonicAt(0,KeyEvent.VK_1);
JButton ref = new JButton("Refresh");
pList.add(ref);
ref.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JScrollPane stable;
try {
stable = memlistpop(stat);
pList.remove(stable);
pList.add(stable);
JOptionPane.showMessageDialog(pList, stable);
} catch (SQLException e) {
e.printStackTrace();
}
}
});
JScrollPane stable = memlistpop(stat);
pList.add(stable);
And this is the memlistpop funcation:
public static JScrollPane memlistpop(Statement stat) throws SQLException{
ResultSet rs = stat.executeQuery("SELECT id,name,level,xp,trophycount FROM avatars");
JTable t = new JTable(DbUtils.resultSetToTableModel(rs)){;
private static final long serialVersionUID = 1L;
public boolean isCellEditable(int row,int column){
return false;
}
};
t.setPreferredSize(new Dimension(500, 300));
JScrollPane stable = new JScrollPane (t);
stable.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
stable.setPreferredSize(new Dimension(500, 323));
//add the table to the frame
return stable;
}
Does anyone have any idea why this isn't working? Thanks!
You may add a layout manager before adding your objects.
If you want to clear the content of your panel, then:
panel.removeAll();
panel.setLayout(new BorderLayout()); // or other layout managers, such as boxlayout, etc
panel.add(myobject); // in this case, pList.add(stable);
That is what I do for myself;
Don't keep removing and adding components from a visible GUI. Instead you can just update the component in the scroll pane by using:
scrollPane.setViewportView( someComponent );
If you ever do need to remove/add components to a visible GUI, then the basic code is:
panel.remove(...);
panel.add(...);
panel.revalidate(); // to invoke the layout manager
panel.repaint();
Related
I'm trying to setup a basic GUI Library that will import a list of books and display each book as a JButton within a scroll pane. But, before getting there I'm just trying to orient the panels first and adding a test button to make sure the basics are working before moving on to the details.
I've tried moving code around to add panels in different orders to see if that was an issue but keep getting the same result. I'm completely new to this, so my understanding of it is very limited.
public class LibraryPanel extends JPanel{
private Library library;
private JPanel bookButtons, importBooks;
JScrollPane bookList;
JTextField importField;
JButton load;
public LibraryPanel() {
setPreferredSize(new Dimension(200,500));
Library library = new Library();
setLayout(new BorderLayout());
this.setBorder(BorderFactory.createTitledBorder("Library"));
// Import Books Panel
importBooks = new JPanel();
importBooks.setLayout(new BoxLayout(importBooks,BoxLayout.X_AXIS));
importBooks.setBorder(BorderFactory.createTitledBorder("Import Books"));
importField = new JTextField(15);
importBooks.add(importField);
load = new JButton("Load");
importBooks.add(load);
this.add(importBooks,BorderLayout.SOUTH);
load.addActionListener(new loadButtonListener());
// Book List buttons
JPanel bookButtons = new JPanel();
bookButtons.setLayout(new BoxLayout(bookButtons,BoxLayout.Y_AXIS));
JButton testButton = new JButton("TEST Button");
bookButtons.add(testButton);
//for(int i = 0; i<library.getBooks().size(); i++) {
// BookButton button = new BookButton(library.getBook(i));
//button.addActionListener(new BookButtonListener());
// bookButtons.add(button);
//}
// Scroll Pane
bookList = new JScrollPane();
bookList.setBorder(BorderFactory.createTitledBorder("Book List"));
bookList.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
bookList.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
this.add(bookList,BorderLayout.CENTER);
bookList.add(bookButtons);
}
private class loadButtonListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String filename = new String(importField.getText());
library.loadLibraryFromCSV(filename);
}
}
}
However, I'm having an issue with the test button not showing up at all within the scroll pane. The panels are there but not the test button.
You can't "add" components to a JScrollPane, this isn't how they work. A JScrollPane uses a JViewport as it's primary component, which is then used to determine when the scrollbars should be used.
See How to Use Scroll Panes for more details
Instead of...
bookList = new JScrollPane();
//...
bookList.add(bookButtons);
simply do...
bookList = new JScrollPane(bookButtons);
//...
//bookList.add(bookButtons);
It seems like the only way to display text with multiple styles in a text area is to use a JEditorPane. To explore this, I wrote a small app to list all the fonts in their font.
Everything works, and the list is displayed in a JEditorPane, which is inside a JScrollPane.
However, it takes a few seconds to launch and to repopulate, because it generates the entire new list before displaying it. The code is below, following MCV. Minimalizing it to just the message and text made less work so the lag is no longer nearly as noticeable, but my question (below) was more about rendering and keeping track of JScrollPane's position anyway than about this app.
FontFrame.java
public class FontFrame extends JFrame {
private FontFrame() {
JFrame frame = new JFrame("Fonts Displayer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FontPanel fontPanel = new FontPanel();
frame.getContentPane().add(fontPanel);
frame.getRootPane().setDefaultButton(fontPanel.getDefaultButton());
frame.setMinimumSize(new Dimension(600, 600));
frame.setPreferredSize(new Dimension(1000, 700));
frame.pack();
frame.setVisible(true);
}
public static FontFrame launchFontFrame() {
return new FontFrame();
}
public static void main(String[] args) {
FontFrame.launchFontFrame();
}
}
FontPanel.java
class FontPanel extends JPanel {
private String message = "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz";
private JEditorPane fontPane;
private JTextField messageInput;
private JButton changeButton;
protected FontPanel() {
buildPanel();
}
private void buildPanel() {
setLayout(new BorderLayout());
// Build message input panel
JPanel inputPanel = new JPanel();
messageInput = new JTextField(message);
messageInput.setFont(new Font("SansSerif", Font.PLAIN, 14));
messageInput.setColumns(40);
JLabel messageLabel = new JLabel("Message:");
changeButton = new JButton("Change");
changeButton.addActionListener((ActionEvent e) -> {
String text = messageInput.getText();
if (!text.isEmpty() && !text.equals(message)) {
message = text;
refreshFontList();
}
});
inputPanel.add(messageLabel);
inputPanel.add(messageInput);
inputPanel.add(changeButton);
// Build scrolling text pane for fonts display
fontPane = new JEditorPane();
fontPane.setContentType("text/html");
fontPane.setEditable(false);
fontPane.setVisible(true);
JScrollPane scrollPane = new JScrollPane(fontPane);
refreshFontList();
// Add components to main panel
add(inputPanel, BorderLayout.NORTH);
add(scrollPane, BorderLayout.CENTER);
}
private void refreshFontList() {
String[] list = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames();
StringBuilder messages = new StringBuilder();
// Set global table style settings
messages.append("<table>");
// Make a row for each font
for (String font : list) {
messages.append("<tr>");
//Append data cells
messages.append("<td>").append(font).append("</td>")
.append("<td style=\"font-family:").append(font).append("\">")
.append(message)
.append("</td>");
messages.append("</tr>");
}
messages.append("</table>");
fontPane.setText(messages.toString());
}
JButton getDefaultButton() {
return changeButton;
}
}
Is there any way of redoing refreshFontList so it can generate only what fontPane would show in its viewport first, possibly by using JScrollBar, and then generate the rest of the list right after so the computation time doesn't cause lag in display? Is there a different component that would work better?
I try to initiate a "JTable", I added all my elements through the form designer and initiated them in the main function of my GUI.
The table is placed inside a "JScrollPanel" and used a "DefaultTableModel" to add the headers and rows.
Whatever I did, I can't make the table to display headers or rows.
What am I missing here?
class Controls extends JPanel{
private JButton compileButton;
private JPanel controls;
private JTabbedPane tabbedPane1;
private JButton insertButton;
private JTable insertedFilesTable;
private JScrollPane insertedFilesViewport;
private JPanel minify;
private JFileChooser insertChooser;
public Controls () {
insertChooser = new JFileChooser();
compileButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
initCompile();
}
});
insertButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
buttonActionPerformed(e);
}
});
}
public void main () {
JFrame frame = new JFrame("Controls");
frame.setLayout(new SpringLayout());
frame.setContentPane(new Controls().controls);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultTableModel model = new DefaultTableModel();
model.addColumn("Files");
model.addColumn("Status");
insertedFilesTable = new JTable(model);
insertedFilesViewport = new JScrollPane(insertedFilesTable);
insertedFilesViewport.setViewportView(insertedFilesTable);
insertedFilesTable.setFillsViewportHeight(true);
String[] data = {"test","test"};
model.addRow(data);
frame.add(insertedFilesViewport);
frame.setSize(500,500);
frame.setVisible(true);
}
private void buttonActionPerformed(ActionEvent evt) {
insertChooser.showSaveDialog(this);
}
}
frame.setLayout(new SpringLayout());
....
frame.add(insertedFilesViewport);
Don't change the layout of the frame to a SpringLayout. There is no reason to do this.
The reason you don't see the scroll pane containing the table is because you didn't use any constraints for the add(...) method. Read the section from the Swing tutorial on How to Use SpringLayout to see how complex the constraints are for adding components.
If you leave the layout as the default BorderLayout, then the component will be added to the CENTER of the BorderLayout by default. The above tutorial also has a section on How to Use BorderLayout you should read.
Hi I am trying to create Scroll Bar for my JFrame. I created JPanel object and set components into JPanel. Then created a JScrollPane object for the panel. Then add the ScrollPane object to JFrame. I am not seeing any scrollbar. Also I am wondering if there is a option in JPanel that would resize the object inside Jpanel automatically according to the zoom level of the JPanel. Any help would be highly appreciated.
public class xmlottgui {
private JPanel Container;
private JFrame frmCreateXml;
private JTextField titlename;
private JLabel lbltitlename;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
xmlottgui window = new xmlottgui();
window.frmCreateXml.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public xmlottgui() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
Container = new JPanel();
Container.setLayout(null);
//JScrollPane pane=new JScrollPane(Container,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
frmCreateXml = new JFrame();
frmCreateXml.setTitle("Create XML");
frmCreateXml.setBounds(100, 100, 1000, 1200);
frmCreateXml.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmCreateXml.getContentPane().setLayout(null);
//Create MenuBar
JMenuBar menuBar = new JMenuBar();
Container.add(menuBar);
JMenu mnFile = new JMenu("File");
menuBar.add(mnFile);
JMenuItem mntmImportFromCsv = new JMenuItem("Import From Excel File");
//Add menu item Exit
JMenuItem mntmexit = new JMenuItem("Exit");
mntmexit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
mnFile.add(mntmexit);
showform();
JScrollPane pane=new JScrollPane(Container,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
pane.setLayout(null);
frmCreateXml.setContentPane(pane);
frmCreateXml.getContentPane().add(pane);
}
private void showform(){
titlename = new JTextField();
titlename.setBounds(164, 27, 749, 26);
Container.add(titlename);
titlename.setColumns(10);
lbltitlename = new JLabel("Title Name");
lbltitlename.setBackground(Color.GRAY);
lbltitlename.setBounds(22, 1000, 90, 16);
Container.add(lbltitlename);
}
This:
pane.setLayout(null);
Will completely disable your JScrollPane and prevent it from working as it will prevent the JScrollPane from displaying and manipulating its view port properly. JScrollPanes have there own very special layout manager, one you never want to muck with unless you are very clever and know what you're doing. As a general rule you should almost never use null layouts.
Also this is not correct:
frmCreateXml.setContentPane(pane);
frmCreateXml.getContentPane().add(pane);
You make pane the contentPane and then add pane to itself.
AND THIS is messing you up:
frmCreateXml.getContentPane().setLayout(null);
You will want to learn about and use the layout managers as it will make your life much easier.
for school I am working on a Java GUI program to store some administrative data.
Now I want to display eventdata from my DB (mysql) into a JPanel with use of a JTextField,
my problem is I can't get the size of the JTextField fixed as it always takes up a lot of place (see picture)
Picture: http://postimg.org/image/5pcklo5n1/
Here's my code, anyone some tips? (I am new to java):
public void editEvent() {
JFrame frEventEdit = new JFrame ("Event Edit Menu");
frEventEdit.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frEventEdit.setVisible(true);
frEventEdit.setSize(700, 500);
//JPanel for displaying data
JPanel pnData = new JPanel();
pnData.setLayout(new BoxLayout(pnData, BoxLayout.PAGE_AXIS));
pnData.add(Box.createRigidArea(new Dimension(0,5)));
pnData.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
pnData.setAutoscrolls(true);
Statement stmt;
try {
stmt = mySql.createStatement();
ResultSet rs = stmt.executeQuery("SELECT name, date, time, type, address, representative FROM events " ) ;
while (rs.next() == true){
System.out.println(rs.getString("name")+" "+rs.getString("date")+" "+rs.getString("time")+" "+rs.getString("type")+" "+rs.getString("address")+" "+rs.getString("representative"));
final JTextField txtEventList = new JTextField(rs.getString("name")+" "+rs.getString("date")+" "+rs.getString("time")+" "+rs.getString("type")+" "+rs.getString("address")+" "+rs.getString("representative"));
pnData.add(txtEventList, BorderLayout.CENTER);
}
} catch (SQLException e) {
e.printStackTrace();
}
JScrollPane scroller = new JScrollPane(pnData);
frEventEdit.add(scroller);
frEventEdit.setLocationRelativeTo(null);
}
Thanks in advance
It happens because you use BoxLayout,try to use FlowLayout which is default for JPanel or another.
In next statement pnData.add(txtEventList, BorderLayout.CENTER); , BorderLayout.CENTER doesn't work, because you doesn't use BorderLayout for your panel.
For fixing size of JTextField, use constructor JTextField(int cols).
For your purposes use JTable as recommended by #AndrewThompson. Tutorial for table.
call frEventEdit.setVisible(true); at the end of construction or like next:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frEventEdit.setVisible(true);
}
});