I'm trying to create a frame with multiple tabs, each with a different list. I've used the Swing UI designer with Intellij to create the "assets" and then modified them in my main class file. I've looked up some examples of creating a JTable using the designer, but these don't use multiple tabs, which I think is the main problem for me right now as I am not able to figure out how to do it.
This is the code for now.
package client;
import javax.swing.*;
import javax.swing.table.TableModel;
import java.awt.event.*;
public class ATCGUI extends GUI {
private JPanel mainPanel;
private JTabbedPane tabbedPanel;
private JPanel tabbedAirportInfo;
private JScrollPane scrollPane;
private JButton addButtonOut;
private JButton deleteButtonOut;
private JButton addButtonIn;
private JButton deleteButtonIn;
private JTable tableOut;
private JTable tableIn;
private JPanel panelOut;
private JScrollPane tabbedPaneOut;
public ATCGUI(String AirportCode) {
this.add(mainPanel);
String airportID = getID(AirportCode);
TableOut(airportID);
pack();
setVisible(true);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
private void TableOut(String airportID){
String[] columnNames = {"Airline", "Destination", "Aircraft"};
Object[][] dataTest = {{"Iberia", "London", "737"}, {"AirEuropa", "Paris", "320"}, {"BritishAirways", "Berlin", "330"}};
JTable TableOut = new JTable(dataTest, columnNames);
setContentPane(panelOut);
}
public static void main(String[] args) {
new ATCGUI("MAD");
}
}
For now it shows the different tabs, but the JTable doesn't appear in any of the tabs. And I did make sure to put the JTable inside a JScrollPane.
I'm pretty new to this so maybe there's something I've missed out or just simply don't know.
Without your JTabbedPane code it will be difficult to suggest what you can "fix" in your own code.
This is a good reference for using a JTabbedPane with multiple tabs:
https://docs.oracle.com/javase/tutorial/uiswing/components/tabbedpane.html
An example of how JTabbedPane might be used with your data:
package whatever;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
public class MyGui extends JFrame {
private JTabbedPane tPane;
MyGui(String t){
super(t);
this.tPane = new JTabbedPane();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
tPane.addTab("Tab 1", createTab());
tPane.addTab("Tab 2", createTab());
tPane.addTab("Tab 3", createTab());
tPane.addTab("Tab 4", createTab());
this.setContentPane(this.tPane);
this.setSize(400, 400);
this.setVisible(true);
}
public static void main(String[] args) {
new MyGui("My Tabbed App");
}
private JScrollPane createTab(){
String[] columnNames = {"Airline", "Destination", "Aircraft"};
Object[][] dataTest = {{"Iberia", "London", "737"}, {"AirEuropa", "Paris", "320"}, {"BritishAirways", "Berlin", "330"}};
JTable tableOut = new JTable(dataTest, columnNames);
return new JScrollPane(tableOut);
}
}
Related
While working on a program, I made some of my fields static i.e. a JTextField for a E-Number. But now this field behaves not as expected, on some of my pages it appears, on some others it disappears.
Since I am not very experienced working with a lot of statics, there might be a concept I am not understanding.
I have created a very simplified but working example of my program (MCVE) if you want to test it.
It shows my overview page at first - the E-Number JTextField is missing.
If you click on the search button, it shows the tracking page - with the E-Number JTextField present.
Both pages contain the same workNumberPanel and I cant find a difference, that would explain the behaviour.
So why is the E-Number JTextField present on the overview page and missing on the tracking page? Any help / explanation is appreciated!
MainProgram.java
import java.awt.CardLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import net.miginfocom.swing.MigLayout;
public class MainProgram extends JFrame {
private static final long serialVersionUID = 1L;
public static JPanel centerPanel = new JPanel();
public static CardLayout contentCardsLayout = new CardLayout();
OverviewPage overviewPage = new OverviewPage();
TrackingPage trackingPage = new TrackingPage();
public void initialize() {
createCenterPanel();
}
private void createCenterPanel() {
centerPanel.setLayout(contentCardsLayout);
overviewPage.setName("overviewPage");
trackingPage.setName("trackingPage");
centerPanel.add(overviewPage, "overviewPage");
centerPanel.add(trackingPage, "trackingPage");
add(centerPanel, "growx, wrap");
}
public MainProgram() {
setBounds(300, 50, 1200, 900);
setLayout(new MigLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
MainProgram window = new MainProgram();
window.setVisible(true);
window.initialize();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
OverviewPage.java
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class OverviewPage extends JPanel {
WorkNumberPanel workNumberPanel = new WorkNumberPanel();
private static final long serialVersionUID = 1L;
public OverviewPage() {
setLayout(new MigLayout());
add(workNumberPanel, "wrap, growx");
}
}
TrackingPage.java
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class TrackingPage extends JPanel {
private static final long serialVersionUID = 1L;
WorkNumberPanel equipmentNumberPanel = new WorkNumberPanel();
public TrackingPage(){
setLayout(new MigLayout("", "grow, fill"));
add(equipmentNumberPanel, "wrap, growx");
}
}
WorkNumberPanel.java
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;
public class WorkNumberPanel extends JPanel {
private static final long serialVersionUID = 1L;
private static final Integer TEXTFIELD_LENGTH = 20;
JPanel mainWorkNumberPanel = new JPanel();
JLabel lblWorkNumber = new JLabel("E-Nr: ");
JLabel lblN_Number = new JLabel("N-Nr.: ");
JLabel lblSNumber = new JLabel("W-Nr.: ");
public static JTextField txtWorkNumber = new JTextField(TEXTFIELD_LENGTH);
JTextField txtNNumber = new JTextField(TEXTFIELD_LENGTH);
JTextField txtSNumber = new JTextField(TEXTFIELD_LENGTH);
JButton btnSearchEntry = new JButton("Search");
public WorkNumberPanel() {
createEquipmentNumberPanel();
btnSearchEntry.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
MainProgram.contentCardsLayout.show(MainProgram.centerPanel, "trackingPage");
}
});
}
private void createEquipmentNumberPanel() {
setLayout(new MigLayout());
mainWorkNumberPanel.setLayout(new MigLayout("", "[][grow, fill][][grow, fill][][grow, fill][]"));
mainWorkNumberPanel.add(lblWorkNumber);
mainWorkNumberPanel.add(txtWorkNumber);
mainWorkNumberPanel.add(lblN_Number);
mainWorkNumberPanel.add(txtNNumber);
mainWorkNumberPanel.add(lblSNumber);
mainWorkNumberPanel.add(txtSNumber);
mainWorkNumberPanel.add(btnSearchEntry);
add(mainWorkNumberPanel, "push, span, growx");
}
}
Probably because when you create your "pages" with this code
OverviewPage overviewPage = new OverviewPage();
TrackingPage trackingPage = new TrackingPage();
the TrackingPage will be the last one to execute the following line
mainWorkNumberPanel.add(txtWorkNumber);
in private void createEquipmentNumberPanel(), and hence that Panel will "own" the JTextField. It only makes sense that a UI component can only be at one place at any given time, otherwise things would get very strange :)
Your statement
Both pages contain the same workNumberPanel and I cant find a difference, that would explain the behaviour.
is simply not true. You are creating a new instance of WorkNumberPanel in both OverViewPage and TrackingPage when you execute the following line
WorkNumberPanel equipmentNumberPanel = new WorkNumberPanel();
So my recommendation is that you find another way of implementing what you want without using a static JTextField (or any other UI component for that matter).
Here you instantiate a OverviewPage, then a TrackingPage .
OverviewPage overviewPage = new OverviewPage();
TrackingPage trackingPage = new TrackingPage();
Both of these classes instantiate a WorkNumberPanel .
WorkNumberPanel add the static JTextField (txtWorkNumber) to their display panel (mainWorkNumberPanel).
A single Component can't be added to several Container objects.
This is what happens to your textfield, since it is static and not an instance variable.
The last addition will win, so the textfield will appear in TrackingPage only, and not in OverviewPage anymore .
Just don't make it static.
First off you need to understand what a static field is. A static field is not related to a particular instance of an object. The field is related to the class itself.
There's quite a good explanation here and here.
Now with regards to your case. A JComponent can only be added to one panel at a time. Adding it to another will remove it from the first.
In your code you are creating multiple instances of 'WorkingNumberPanel'. When you do this you add the text fields to the panel, including the static text field txtWorkNumber. Since the field txtWorkNumber is static you are adding the same object to multiple components, which as I mentioned above will remove it from anywhere it was previously added.
One possible way of solving this would be to store the value from txtWorkNumber in a static variable and create a new instance (non-static) text field to add to the panel.
As of late I've been developing a (very) small GUI application in Java. I'm extremely new to Swing and Java in general, but up until now I have been able to get everything to work the way I want it to. However, after cleaning up my code, when I run the program nothing but the border of the window appears. What am I doing wrong and how can I fix my code? Thanks ahead of time!
For the sake of saving space I've made Pastebin links to all of my classes (besides Main).
Main Class
package me.n3rdfall.ezserver.main;
public class Main {
public static GUI g = new GUI();
public static void main(String[] args) {
g.showWindow(800, 500);
}
}
GUI Class
http://pastebin.com/gDMipdp1
ButtonListener Class
http://pastebin.com/4XXm70AD
EDIT: It appears that calling removeAll() directly on 'frame' actually removed essential things other than what I had added. By calling removeAll() on getContentPane(), the issue was resolved.
Quick hack: Remove the removeAll() functions.
public void homePage() {
// frame.removeAll();
// mainpanel.removeAll();
// topbar.removeAll();
I'm not sure what you're trying to achieve, but that will at least show some items. If I were you I would rebuild this GUI by extending JFrame. It will make your code a little easier to read.
I also think what you are trying to achieve with the buttons is to switch layouts, you can do this in an easier way by using CardLayout
Example (has nothing to do with your code, but to demonstrate):
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example extends JFrame implements ActionListener {
private JButton leftButton;
private JButton rightButton;
private CardLayout cardLayout = new CardLayout();
JPanel cards = new JPanel(cardLayout);
final static String LEFTPANEL = "LEFTPANEL";
final static String RIGHTPANEL = "RIGHTPANEL";
JPanel card1;
JPanel card2;
public Example() {
JPanel topPanel = new JPanel();
addButtons(topPanel);
add(topPanel, BorderLayout.NORTH);
add(cards, BorderLayout.CENTER);
//Initiates the card panels
initCards();
setTitle("My Window");
setSize(300, 300);
setLocationRelativeTo(null);
setVisible(true);
}
private void initCards() {
card1 = new JPanel();
card2 = new JPanel();
card1.setBackground(Color.black);
card2.setBackground(Color.red);
cards.add(card1, LEFTPANEL);
cards.add(card2, RIGHTPANEL);
}
private void addButtons(Container con) {
leftButton = new JButton("Left Button");
leftButton.addActionListener(this);
rightButton = new JButton("Right Button");
rightButton.addActionListener(this);
con.add(leftButton, BorderLayout.WEST);
con.add(rightButton, BorderLayout.EAST);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(leftButton)) {
//Change cardlayout
cardLayout.show(cards, LEFTPANEL);
} else if(e.getSource().equals(rightButton)) {
//Change cardlayout
cardLayout.show(cards, RIGHTPANEL);
}
}
public static void main(String[] args) {
new Example();
}
}
In trying to run my basic GUI application from Main I have somehow managed to first make the GUI show up (but it was smaller than what I set the size to within the code and not showing any components) then magically (after adding pack() and setlocationrelativeto(null)) it does not pop up at all. I am using Netbeans (if that helps), in Main it gives me a tooltip that my GUI is "never used" so it runs and outputs "Finished building" rather than continuing to run and showing the GUI. I have provided 2 sets of code (1) main method and (2) GUI class. Please let me know if I'm being confusing as of course it makes sense in my head but may be communicated badly. I have not included the complete code but if it is necessary please let me know and I will do so.
package logTime;
public class LogInTime {
public static void main(String[] args) {
try{
LogAppFrame app = new LogAppFrame(); //IDE gives tooltip that app is unused
}
catch(Exception e){
System.err.println("\n\nError Occurred: "); //am going to print message later
}
}
}
The actual GUI code - does not include imports or actionlisteners:
public void LogAppFrame(){
frame = new JFrame("Time Log Application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cl = new CardLayout();
frame.getContentPane().setLayout(cl);
//frame.setLayout(cl);
frame.setSize(new Dimension(375,385));
logNewFrame = new JPanel();
logNewFrame.setLayout(new GridLayout(5,1));
logNewFrame.setBorder(new EmptyBorder(20,20,20,20));
frame.getContentPane().add(logNewFrame, "logNewFrame");
historyFrame = new JPanel();
historyFrame.setLayout(new GridLayout(2,1)); //given 0 for rows to add numerous rows
historyFrame.setBorder(new EmptyBorder(20,20,20,20));
frame.getContentPane().add(historyFrame, "historyFrame");
.
.
.
//added lots of components but will not include code as there is no error within this portion of code - i used to have both Main and LogAppFrame class all together and my GUI worked and showed components but I felt it may be best practice not to do it this way and cardlayout wasnt working
.
.
.
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Adding SSCE below:
package logTime;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.*;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class LogAppFrame{
private static JFrame frame;
private static CardLayout cl;
//menu option components
/**
* Help option: How To Use/Read Me - explains how to use it 8 Hour Day -
* shows the arrival and leave time based on lunch type
*/
/**
* Log New Date option: shows screen to input new values into date
*/
/**
* View Past Dates option: shows all past dates since forever - may add
* month tabs later
*/
/**
* Edit Past Date option: doesnt exist yet but will be added to View Past
* menu option as side button to edit any old date
*/
private static JMenuBar menuBar = new JMenuBar();
private static JMenu help;
private static JMenuItem logNewDate;
private static JMenuItem viewPastDates;
private static JMenuItem workDay;
private static JMenuItem about;
//Log New Date components
/**
* 4 labels, 1 button, 1 calendar, 2 dropdowns, 2 textfields, 5x2 gridlayout
*/
private static JLabel dateToday;
private static JLabel timeInToday;
private static JLabel timeOutToday;
private static JLabel lunchTypeToday;
private static JLabel timeColon1;
private static JLabel timeColon2;
private static JButton saveButton;
private static JComboBox month;
private static JComboBox day;
private static JComboBox year;
private static JComboBox amPm1;
private static JComboBox amPm2;
private static JComboBox hrTimeIn;
private static JComboBox hrTimeOut;
private static JComboBox minTimeIn;
private static JComboBox minTimeOut;
private static JPanel dateTodayPanel;
private static JPanel timeInPanel;
private static JPanel timeOutPanel;
private static JPanel lunchTypePanel;
private static JPanel saveButtonPanel;
private static JComboBox lunchType;
//View Past Dates components
/**
* 4x*infinitiy* gridlayout or have a flowlayout, 4 labels
*/
private static JLabel pastDates;
private static JLabel pastTimeIns;
private static JLabel pastTimeOuts;
private static JLabel pastLunchTypes;
private static JPanel headers; //holds header labels
private static JPanel oldLogs; //will hold all past log panels
//Frames to hold the logNew and viewOld views
private static JPanel logNewFrame;
private static JPanel historyFrame;
public void LogAppFrame(){
frame = new JFrame("Time Log Application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cl = new CardLayout();
frame.getContentPane().setLayout(cl);
//frame.setLayout(cl);
frame.setSize(new Dimension(375,385));
logNewFrame = new JPanel();
logNewFrame.setLayout(new GridLayout(5,1));
logNewFrame.setBorder(new EmptyBorder(20,20,20,20));
frame.getContentPane().add(logNewFrame, "logNewFrame");
historyFrame = new JPanel();
historyFrame.setLayout(new GridLayout(2,1)); //given 0 for rows to add numerous rows
historyFrame.setBorder(new EmptyBorder(20,20,20,20));
frame.getContentPane().add(historyFrame, "historyFrame");
//Menu components
menuBar = new JMenuBar();
help = new JMenu("Help");
logNewDate = new JMenuItem("Log New Date");
viewPastDates = new JMenuItem("View Past Dates");
workDay = new JMenuItem("8 Hour Day");
about = new JMenuItem("How To ...");
help.add(workDay);
help.add(about);
menuBar.add(logNewDate);
menuBar.add(viewPastDates);
menuBar.add(help);
frame.setJMenuBar(menuBar);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
You have written void before the thing that ought to be a constructor. So it is mistaken as a method by the compiler which never gets called. Unfortunately the compiler generates a no-op constructor for you in such a case. Just remove the void keyword.
And by the way, remove all the nasty static keywords from the fields. That hurts.
If you want to write simple gui applications you should check WindowBuilder. It's drag and drop gui for java that actually works.
I am using a JScrollPane to wrap a JTable. Depending on the configuration, there is some space that is not occupied by the table. It is drawn gray (it looks like it is transparent and you can just see the component in the back). How can I set this area to be a certain color?
Here is a SSCCE to illustrate.
import java.awt.Color;
import java.util.Vector;
import javax.swing.JDialog;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class DialogDemo extends JDialog {
public static void main(final String[] args) {
final DialogDemo diag = new DialogDemo();
diag.setVisible(true);
}
public DialogDemo() {
super();
setTitle("SSCCE");
final Vector<Vector<String>> rowData = new Vector<Vector<String>>();
final Vector<String> columnNames = new VectorBuilder<String>().addCont("Property").addCont("Value");
rowData.addElement(new VectorBuilder<String>().addCont("lorem").addCont("ipsum"));
rowData.addElement(new VectorBuilder<String>().addCont("dolor").addCont("sit amet"));
rowData.addElement(new VectorBuilder<String>().addCont("consectetur").addCont("adipiscing elit."));
rowData.addElement(new VectorBuilder<String>().addCont("Praesent").addCont("posuere..."));
final JTable table = new JTable(rowData, columnNames);
JScrollPane pane = new JScrollPane(table);
// ************* make that stuff white! *******************
table.setBackground(Color.white);
table.setOpaque(true);
pane.setBackground(Color.white);
pane.setOpaque(true);
// ************* make that stuff white! *******************
add(pane);
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
}
class VectorBuilder<T> extends Vector<T> {
public VectorBuilder<T> addCont(final T elem) {
addElement(elem);
return this;
}
}
}
And here you can see the area, which I want to "colorize". In the SSCCE, I try to do that by using setOpaque(boolean) and setBackgroundColor(Color) of the table and scroll pane, with no success.
Can you tell me, what I am doing wrong?
Instead of this:
table.setBackground(Color.white);
table.setOpaque(true);
pane.setBackground(Color.white);
pane.setOpaque(true);
call:
pane.getViewport().setBackground(Color.WHITE);
Please have a look at the following code
import java.awt.*;
import javax.swing.JTable;
import javax.swing.*;
public class Table extends JFrame
{
private JTable table;
public Table()
{
String[] columnNames = {"first name","last name","address"};
Object[][]data = {{"John","Kane","NY"},{"Nayomi","Writz","NY"}};
table = new JTable(data, columnNames);
getContentPane().add(table);
this.pack();
this.setVisible(true);
}
public static void main(String[]args)
{
new Table();
}
}
I haven't used JTable before, so this is my first attempt. In here, it is not showing the column names, just showing the data. Why is that? Please help!
You need to put it in a JScrollPane or similar.
See the top of the API docs for JTable, and JScrollPane.