may I know how to display out the table when the menu bar is clicked?
Below is my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
public class Exercise03 extends JFrame {
public Exercise03() {
String[] columns = {
"No", "DO NUMBERS", "INVOICE NUMBERS", "OUTLET", "SUBMITTED BY", "CHECKED BY"
};
Object [][] input = new Object[][] {
{"1", "NKK/DO200100001", "NKK/IV200100001", "K", "A", "B"}
};
JMenuBar menuBar;
JMenu menu;
JMenuItem menuItem1;
menuBar = new JMenuBar();
menu = new JMenu ("Menu");
menu.setMnemonic(KeyEvent.VK_A);
menuBar.add(menu);
menuItem1 = new JMenuItem("Invoice", KeyEvent.VK_I);
menu.add(menuItem1);
menuItem1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
JTable menuItem1 = new JTable(input, columns);
JScrollPane pane = new JScrollPane(menuItem1);
pane.add(menuItem1);
pane.setVisible(true);
}
});
setJMenuBar(menuBar);
Container cp = getContentPane();
cp.setLayout(new FlowLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Documentation Checklist");
setSize(300,100);
setVisible(true);
}
public static void main (String[]args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Exercise03();
}
});
}
}
Right now I am able to display out the "menu" bar and when I clicked it, it shows one submenus which is "Invoice" but when I clicked the submenu "Invoice", it does not shows out the table below the menu bar.
My expected output is when I click the submenu "Invoice", it will shows up a table below the menu bar.
So may I know how to code to display such result ?
First of all you need to learn how to use a JScrollPane:
JScrollPane pane = new JScrollPane(menuItem1);
//pane.add(menuItem1);
Only the first statement is needed. The scroll pane has a "viewport" to display the component. So the table needs to be added to the viewport, which is done automatically when you create the scroll pane with the table as the parameter in the constructor.
Read the section from the Swing tutorial on How to Use Scroll Panes for more details on how the scroll pane works.
Then to dynamically add the scroll pane to the frame:
Don't change the layout to a FlowLayout. The default BorderLayout will be a better layout manager for the frame. It will allow components to resize dynamically as the frame is resized.
You create a JScrollPane, but you never add it to the frame. So you need to add the scroll pane to the frame. The setVisible() statement is not needed since all Swing components are visible by default
Once you add the scroll pane to the frame you need to invoke revalidate() on the panel you add the scroll pane to. In this case since you add it to the content pane you can just invoke revalidate() on the frame. The revalidate() will invoke the layout manager to give the scroll pane a size and location.
The other solution is to create the JScrollPane in the constructor of your class and add it to the frame. You would then need to save the scroll pane as an instance variable of your class. Then when you click on the menu item you can create the JTable and add the table to the scroll pane using:
scrollPane.setViewportView( menuItem1 );
then you don't need to worry about the revalidate().
Related
I need help understanding how JTable can be implemented. My JTable does not show up when given header names and data, I have tried pack() (makes my everything but my menu disappear), I have tried setFillsViewportHeight(true) and nothing updated. Any help or guidance would be appreciated.
// Main
public static void main(String[] args) {
Main window = new Main("A Project");
window.setBounds(30, 30, 700, 500);
window.setVisible(true);
}
// Displays a box with a menu bar that has file and about options(code not shown):
public Main(String title) {
JMenuBar menuBar = new JMenuBar(); // Window menu bar
setTitle(title);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setJMenuBar(menuBar); // Add the menu bar to the window
}
// This section of code is inside action listener when you click menu bar's file then load a file:
// Nothing appears:
String[] columnNames = {"ID","First Name","Last Name","Program","Level","USERNAME"};
ArrayList[][] data = loadFileRoster.getRosterData();
JTable table = new JTable(data,columnNames);
JScrollPane scrollPane = new JScrollPane();
table.add(scrollPane);
table.setVisible(true);
ArrayList[][] data = loadFileRoster.getRosterData();
JTable table = new JTable(data,columnNames);
I'm not aware that you can create a JTable using an ArrayList containing your data (unless is new in JDK 14)
JScrollPane scrollPane = new JScrollPane();
table.add(scrollPane);
You don't add a scroll pane to a table. You add a JTable to the JViewport of a JScrollPane. This is done by using:
JScrollPane scrollPane = new JScrollPane( table );
You then add the scroll pane to the frame.
table.setVisible(true);
Swing components are visible by default. The setVisible(true) is unnecessary.
Read the section from the Swing tutorial on How to Use Tables for working examples.
Download the example and modify them. They will show you how to better structure your code.
I'm trying to develop a form of an accordion menu. There are a small number (2-12) options that can be toggled on/off. When toggled on, there will be a JPanel with additional settings that become visible. When toggled off, the additional settings will not be visible.
I've created a SelectableExpandablePanel class that extends JPanel and implements ActionListener and ComponentListener. The panel holds two things - a JToggleButton and a child Component (which will typically be a JPanel, but I don't want to limit myself for future reuse of this concept) in a BoxLayout to enforce one column. When the toggle button is selected, the child becomes visible. When the toggle is deselected, the child is hidden.
When I use this component, I intend to put it on a JPanel inside of a JScrollPane, as demonstrated in the sample main method.
There appear to be two problems that I'm having trouble overcoming:
If I don't specify a JFrame size, it's only large enough for the width of each child and tall enough for three buttons. When I click on the button, I would expect the JScrollPane to do its thing and generate a vertical scroll bar. This isn't happening.
I'd like the toggle buttons to be the full width of the JPanel that contains them. I thought what I did in the constructor plus the Component Listener would handle that, but it doesn't.
What is provided below compiles and has a main method. If compiled and executed, it drives the component I'm building to provide a test frame and the ability to reproduce the issues I'm talking about.
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
public class SelectableExpandablePanel extends JPanel implements
ActionListener, ComponentListener {
private JToggleButton titleButton;
private JComponent childComponent;
public SelectableExpandablePanel(JComponent child) {
this(child, null, null);
}
public SelectableExpandablePanel(JComponent child, String title) {
this(child, title, null);
}
public SelectableExpandablePanel(JComponent child, String title,
String tooltip) {
super();
if (child == null) {
throw new IllegalArgumentException("Child component cannot be null");
}
childComponent = child;
titleButton = new JToggleButton();
titleButton.setText(title);
titleButton.addActionListener(this);
titleButton.setPreferredSize(new Dimension(getSize().width, titleButton
.getPreferredSize().height));
titleButton.setToolTipText(tooltip);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setPreferredSize(new Dimension(childComponent.getPreferredSize().width,
titleButton.getPreferredSize().height));
setSize(new Dimension(childComponent.getPreferredSize().width,
titleButton.getPreferredSize().height));
add(titleButton);
this.addComponentListener(this);
}
public void actionPerformed(ActionEvent e) {
if (titleButton.isSelected()) {
add(childComponent);
setSize(new Dimension(childComponent.getPreferredSize().width,
titleButton.getPreferredSize().height
+ childComponent.getPreferredSize().height));
} else {
remove(childComponent);
setSize(new Dimension(childComponent.getPreferredSize().width,
titleButton.getPreferredSize().height));
}
invalidate();
revalidate();
}
public void componentHidden(ComponentEvent arg0) {
// Do nothing
}
public void componentMoved(ComponentEvent arg0) {
// Do nothing
}
public void componentResized(ComponentEvent arg0) {
titleButton.setSize(this.getWidth(),
titleButton.getPreferredSize().height);
}
public void componentShown(ComponentEvent arg0) {
// Do nothing
}
public static void main(String[] args) {
JScrollPane scrollPane = new JScrollPane();
// These panels simulates a complex, multi-line configuration panel.
JPanel testPanel = new JPanel();
testPanel.setLayout(new BoxLayout(testPanel, BoxLayout.Y_AXIS));
testPanel.add(new JLabel("Test JLabel"));
testPanel.add(new JLabel("Test JLabel 2"));
testPanel.add(new JLabel("Test JLabel 3"));
JPanel testPanel2 = new JPanel();
testPanel2.setLayout(new BoxLayout(testPanel2, BoxLayout.Y_AXIS));
testPanel2.add(new JLabel("Test JLabel"));
testPanel2.add(new JLabel("Test JLabel 2"));
testPanel2.add(new JLabel("Test JLabel 3"));
JPanel testPanel3 = new JPanel();
testPanel3.setLayout(new BoxLayout(testPanel3, BoxLayout.Y_AXIS));
testPanel3.add(new JLabel("Test JLabel"));
testPanel3.add(new JLabel("Test JLabel 2"));
testPanel3.add(new JLabel("Test JLabel 3"));
// This panel simulates the panel that will contain each of the
// SelectableExpandablePanels.
JPanel testHolder = new JPanel();
testHolder.setLayout(new BoxLayout(testHolder, BoxLayout.Y_AXIS));
testHolder.add(new SelectableExpandablePanel(testPanel, "Test"));
testHolder.add(new SelectableExpandablePanel(testPanel2, "Test 2"));
testHolder.add(new SelectableExpandablePanel(testPanel3, "Test 3"));
// We add the test holder to the scroll pane. The intention is that if
// the expansion is too big to fit, the holding JFrame won't expand, but
// the scroll pane will get scroll bars to let the user scroll up and
// down through the toggle buttons and any enabled items.
scrollPane.setViewportView(testHolder);
JFrame testFrame = new JFrame("Expandable Panel Test");
testFrame.getContentPane().add(scrollPane);
testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
testFrame.pack();
testFrame.setVisible(true);
}
}
Don't try to manage the sizes yourself:
//titleButton.setPreferredSize(new Dimension(getSize().width, titleButton.getPreferredSize().height));
titleButton.setToolTipText(tooltip);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
//setPreferredSize(new Dimension(childComponent.getPreferredSize().width, titleButton.getPreferredSize().height));
//setSize(new Dimension(childComponent.getPreferredSize().width, titleButton.getPreferredSize().height));
Also, get rid of the setSize() code in the ActionListener. This will be ignored anyway as the layout manager will determine the size.
The scrollbars will appear when the preferred size of the panel is greater than the size of the scrollpane. If you hardcode the preferred size then you default the purpose of the layout manager and the preferred size won't change as you add/remove components.
Note for something like this I generally use a BorderLayout. Put the button in the PAGE_START and the other panel in the CENTER. The components will automatically fill the space available.
Remove all the setSize/setPreferredSize calls and let the LayoutManager do its thing.
To allow the JButtons to fill the width of the panel, you can use a BorderLayout (for instance, add the button to CENTER, and the child container to SOUTH and remove all those setSize values to let the LayoutManager handle it).
I have a question regarding JFrame with a list.
I created a help menu button. Now the thing is:
When clicked a new window pops up as should. In this window I want to have a list with some formulas by name. Once a formula in the list is clicked I want to display in the same screen what the formula stands for.
It has to be something like formulas on the left in a scrollable list and in the same screen on the right in some sort of text box the description of the clicked formula.
Does anyone know how to do this?
menuItem = new JMenuItem("Help");
menuItem.setMnemonic(KeyEvent.VK_H);
menuItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JFrame help = new JFrame("HELP");
help.setTitle("Help");
help.setSize(400,200);
help.setLocationRelativeTo(null);
help.setDefaultCloseOperation(help.DISPOSE_ON_CLOSE);
help.setVisible(true);
help.add(label);
String labels[] = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "x", "y"};
JList list = new JList(labels);
JScrollPane scrollPane = new JScrollPane (list);
Container contentPane = help.getContentPane();
contentPane.add(scrollPane, BorderLayout.CENTER);
}
});
Suggestions:
The help menu that pops up should be a dialog of some sort, perhaps a non-modal JDialog.
You should have it use a CardLayout so that it initially shows formula names, perhaps in a JList held by a JScrollPane.
When a JList item is selected, swap views via the CardLayout and display the appropriate formula.
Links:
CardLayout Tutorial
JList Tutorial
Edit
You state in comment,
It has to be something like i have my formulas on the left with a scrollbar, and in the right side of the screen some sort of textbox with the description of the formula.
Shouldn't this any any other pertinent information and restrictions be part of your original question? If I were you, I'd edit the original post and supply all necessary information so that we can fully understand your problem including pertinent code (best as an sscce). So...
Use another layout manager such as a GridLayout or better yet a BorderLayout to allow you to show multiple JPanels in another JPanel. I'll leave it to you to find the links to the Swing layout manager tutorials.
You can still use a CardLayout to swap the equations shown on the display JPanel.
Edit 2
Regarding your latest code post:
Again, the dialog window should be a JDialog not a JFrame. The window is dependent on the window that is displaying it and so should not be an independent application window such as a JFrame.
I'd place the JScrollPane in the BorderLayout.LINE_START position and the CardLayout using equation JPanel in the BorderLayout.CENTER position.
You don't have to use a CardLayout. If the equations are nothing but basic text, you can simply change the text of a JLabel.
Or if images, then swap the ImageIcon of a JLabel.
Or if a lot of text, then text in a non-editable, non-focusable JTextArea
Edit 3
is there a way to set the size to a fixed size of the scrollpane BorderLayout.LINE_START?
Rather than trying to set the size of anything, consider calling some methods on your JList, methods such as, setPrototypeCellValue(E prototypeCellValue) and setVisibleRowCount(int visibleRowCount) which will allow the component to set its own preferredSize based on reasonable data and initial assumptions. Please check the JList API for the details on these and other JList methods.
Here comes a basic implementation.
How the second (formula) window may look like:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Window;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class FormulaWindow extends JDialog {
public FormulaWindow(final Window parent) {
super(parent, "Formula window", ModalityType.MODELESS);
final Container cp = getContentPane();
cp.setLayout(new BorderLayout());
setSize(500, 400);
final Map<String, String> formulaDescritions = new HashMap<>();
formulaDescritions.put("Formula 1", "<html>How the world works.</html>");
formulaDescritions.put("Formula 2", "<html>How woman work.</html>");
formulaDescritions.put("Formula 3", "<html>How programming works.</html>");
final JList<String> formulaList = new JList<String>(new Vector<String>(formulaDescritions.keySet()));
formulaList.setPreferredSize(new Dimension(100, 100));
final JLabel descriptionLabel = new JLabel();
descriptionLabel.setVerticalAlignment(SwingConstants.TOP);
formulaList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent evt) {
final JList<String> list = (JList<String>) evt.getSource();
descriptionLabel.setText(formulaDescritions.get(list.getSelectedValue()));
}
});
cp.add(new JScrollPane(formulaList), BorderLayout.WEST);
cp.add(new JScrollPane(descriptionLabel), BorderLayout.CENTER);
}
}
How to open it on selection of a menu item in the main window:
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
public class MainWindow extends JFrame {
private class ShowFormulaWindowAction extends AbstractAction {
public ShowFormulaWindowAction() {
super("Show formulas...");
}
public void actionPerformed(ActionEvent actionEvent) {
FormulaWindow formulaWindow = new FormulaWindow(MainWindow.this);
formulaWindow.setVisible(true);
}
}
public MainWindow() {
super("Main window");
JMenu fileMenu = new JMenu("Extras");
fileMenu.add(new JMenuItem(new ShowFormulaWindowAction()));
JMenuBar menuBar = new JMenuBar();
menuBar.add(fileMenu);
setJMenuBar(menuBar);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
public static void main(final String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MainWindow mainWindow = new MainWindow();
mainWindow.setSize(350, 250);
mainWindow.setVisible(true);
}
});
}
}
Further notes:
The secondary window should not be a JFrame but rather a JDialog. In that way
it does not show another icon on the task bar
it can be "owned" by the main window, causing the dialog to be closed automatically, when the owner is closed
In java, I have been trying to create a panel that can accept other panels with a scroll bar.
I tried using gridlayout, and this works fine, except for the fact that if I only add a few panels, it grows those panels to fit the size of the parent panel.
I tried using flowlayout, but this makes the panels flow horizontally as there is a scroll bar.
How do I make it so I can add panels to the parent panel starting at the top and make them always the same size(or their preferred size).
Also, when I add panels to the parent panel after an event, they do not appear until after I move or resize the form. How do I make it repaint? calling repaint() on it did not work.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
/** This lays out components in a column that is constrained to the
top of an area, like the entries in a list or table. It uses a GridLayout
for the main components, thus ensuring they are each of the same size.
For variable height components, a BoxLayout would be better. */
class ConstrainedGrid {
ConstrainedGrid() {
final JPanel gui = new JPanel(new BorderLayout(5,5));
gui.setBorder(new EmptyBorder(3,3,3,3));
gui.setBackground(Color.red);
JPanel scrollPanel = new JPanel(new BorderLayout(2,2));
scrollPanel.setBackground(Color.green);
scrollPanel.add(new JLabel("Center"), BorderLayout.CENTER);
gui.add(new JScrollPane(scrollPanel), BorderLayout.CENTER);
final JPanel componentPanel = new JPanel(new GridLayout(0,1,3,3));
componentPanel.setBackground(Color.orange);
scrollPanel.add(componentPanel, BorderLayout.NORTH);
JButton add = new JButton("Add");
gui.add(add, BorderLayout.NORTH);
add.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent ae) {
componentPanel.add(new JTextField());
gui.validate();
}
});
Dimension d = gui.getPreferredSize();
d = new Dimension(d.width, d.height+100);
gui.setPreferredSize(d);
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ConstrainedGrid cg = new ConstrainedGrid();
}
});
}
}
Assuming JScrollPane, see Sizing a Scroll Pane. For convenience, Scrollable clients such as JTable offer setPreferredScrollableViewportSize(), but you can always set the viewport's size explicitly.
I would like to customize my titlebar, minimize-, maximize- and the close-button. So I used setUndecorated(true); on my JFrame, but I still want to be able to resize the window. What is the best way to implement that?
I have a border on the RootPane, and I could use MouseListeners on the Border or the RootPane. Any recommendations?
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.border.LineBorder;
public class UndecoratedFrame extends JFrame {
private LineBorder border = new LineBorder(Color.BLUE,2);
private JMenuBar menuBar = new JMenuBar();
private JMenu menu = new JMenu("File");
private JMenuItem item = new JMenuItem("Nothing");
public UndecoratedFrame() {
menu.add(item);
menuBar.add(menu);
this.setJMenuBar(menuBar);
this.setUndecorated(true);
this.getRootPane().setBorder(border);
this.setSize(400,340);
this.setVisible(true);
}
public static void main(String[] args) {
new UndecoratedFrame();
}
}
As you said, you have a border on your root pane. As a consequence, there is at least one location (below the palce where your border is drawn) where your root pane is the upmost component. As a consequence, you can add it a mouse listener and a mouse motion listener.
When your root pane is clicked (and the mouse button is pressed), your mouse and motion listeners will inform you of the initial and actual mouse position. As a consequence, you can update your frame size of the offset between both values, making your frame resizable.
Resizing Components shows one way.
I found a nice method in RootPane that gave me this functionality, so now I only have to find out how to customize the titlebar and the buttons on it.
I added this.getRootPane().setWindowDecorationStyle(JRootPane.FRAME); in my constructor for UndecoratedFrame.
There is some more reading about this on Sexy Swing App – The Unified Toolbar and How to control window decorations