How to Have a Jtabbedpane with a Jmenubar

How to add a JMenuBar to a JTabbedPane?

Actually, you cannot set menu bar to JTabbedPane.
You need to add JInternalFrame inside one of the tabs of JTabbedPane, then
you can call setJMenuBar of JInternalFrame.

Here is a simple example:

JInternalFrame jInternalFrame = new JInternalFrame();
jMenuBar = new javax.swing.JMenuBar();
jMenu1 = new JMenu("Save");
jMenu2 = new JMenu("Open");
jMenuBar.add(jMenu1);
jMenuBar.add(jMenu2);
jInternalFrame.setJMenuBar(jMenuBar);
tabbedPane.addTab("tab3", jInternalFrame);

MVC and controlling a jMenubar depending on selected jTabbedpane from a Control class

First of all do not subclass Swing components unless you need new component with extended functionality.

Now, the way to deal with the menu:

  1. Create empty JMenuBar.

  2. Write a method to clear menu bar and fill it with menus/actions based on selected tab

  3. Add change listener to your tabbed pane such that it calls previously described method

JTabbedPane add different class constructor to a tab

What do you mean by use the JMenuBar? I would suggest looking into OOP and encapsulation. There's a guy on YouTube that I think does an excellent job covering stuff like that as well as several Design Patterns, the channel name I believe is DerekBanas. He'll show up if you google it.

A quick answer to your question is you're going to want to pass something into the constructor of the JPanel class either that or put the main method in the JPanel class, here's a quick example of one way to do this...

JMenuItem is - add new record , in first tab when I choose this JMenuItem he opens me a frame, where are JLabel and JTextField. Then there is a second tab, I click on the same JMenuItem and it's summons new JFrame which have it's own JLabel and JTextField.

public class TestFrame extends JFrame {

private ActionManager actionManager

private JMenuBar mb;
private JMenu file;
private JMenuItem openDialog1;
private JMenuItem openDialog2;

public TestFrame() {

this.actionManager = new ActionManager();

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setContentPanel(panel);
setJMenuBar(createMenuBar());
pack();
}

private JMenuBar createMenuBar() {
mb = new JMenuBar();
file = new JMenu("File");
openDialog2 = new JMenuItem("Open Dialog 2");
openDialog1 = new JMenuItem("Open Dialog 1");
openDialog2.addActionListener(actionManager.openDialog2Action);
openDialog1.addActionListener(actionManager.openDialog1Action);

//here i would add conditional code that added the correct
//menus to the menubar and menuitems to the correct menus and call
//this method from a `ChangeListener` that listens for tab changes so
//it recreates a new menu with the correct components for the selected
//tab but i added them to the same menu to demonstrate using specific actions
//for each menu item, it doesn't matter which menu they're attached to their
//action wont be called unless that JMenuItem is clicked.
//this method can be used for any type of button as well, commonly with
//toolbars, so you can reuse actions like copy, paste, new, open, save, etc

file.add(openDialog1);
file.add(openDialog1);
mb.add(file);

return mb;
}

public static void main(String[] args) {
TestFrame frame = new TestFrame();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

And the panel class...

public class ActionManager {

public ActionManager() {

}

Action openDialog1Action = new AbstractAction("Open Dialog 1") {
JOptionPane.showMessageDialog(null, "Dialog 1");
}

Action openDialog2Action = new AbstractAction("Open Dialog 2") {
JOptionPane.showMessageDialog(null, "Dialog 2");
}

}

All this code does is use public methods to access private fields from the class (encapsulation) and the TestFrame object is passed into the TestPanel constructor so we can use the getter methods inside TestFrame from the TestPanel class. I also added the ActionListener as part of the TestPanel class because that's another way to use the menubar components in the panel class. Can you tell me specifically what you're trying to accomplish, or possibly post a small portion of your current code? This is one of several ways to do what you asked but it may not be the preferred way depending on why you want access to them from the panel in the first place, the more specific your questions are the more help I can be. Good luck.

Choice appears over JMenu

You are mixing Swing components (JMenu, JTabbedPane) with an AWT component (Choice). This leads to various problems including the overlap of the Choice component over the JMenu.

Use JComboBox instead of Choice

How to add JTable into JTabbedPane?

This is how you're creating a Panel with a Table in the screen class.

studentTable = new StudentTable();

This is what the constructor for StudentTable looks like.

public StudentTable() {}

You see the problem here? You're calling an empty constructor.

You can try to fix it by actually creating the table, either in the table constructor or by explicitly calling createTable() on the object.

So either in Screen do.

// Tabs
tabbedPane.add("List", PList);
tabbedPane.add("Chart", PChart);
add(tabbedPane);
studentTable.createTable(); // Create the table
PList.add(studentTable);
validate(); // Revalidate the frame

Or in the create the table in the StudentTable class.

public StudentTable() {
createTable();
}

See, that simple. Does it work now? Not really. StudentTable is a Panel, and you never actually add anything to it. So you're just adding an empty Panel to your TabbedPane.

You need to actually add the table to the Panel at some point. So go back to the StudentTable Class and add add(table) at the end of the createTable() method. Or if you're calling createTable() in the constructor, you can also add this line in the constructor, below createTable().

public StudentTable() {
createTable();
add(table);
}

Can you see a table now? Yes you can. Can you see all the values in the table? No you cannot. That's because the table isn't scrollable. You need to add it to a ScrollPane.

The easiest way to go about it is to create a ScrollPane in the StudentTable Class. Add the Table to the ScrollPane and then add the ScrollPane to the Panel.

Go back to where ever you wrote add(table) in the StudentTable Class and replace with.

JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
add(scrollPane);

This should fix your problem for now.

As an additional, I want to point out that you use way too many class fields. For example in the StudentTable Class, name, lastName, letterGrade, studentId, quiz1, quiz2, project, midterm, finalGrade, average and scanner have no use being a field. All but one are not attributes of the table, they don't represent an instance of a table. They represent a Student I would suggest you to take a look at this answer to a related question.

You should never use a field to simplify passing data from one method to another method. That's simply not its purpose. Doing so also makes your methods intrinsically thread unsafe or require synchronization.

You also do not need a main() method in every single class. It just serves as an entry point to the code when it starts, that's it.

Regarding the getters and setter, only add the ones you need. Your screen Class accesses none of the fields in the StudentTable class (understandably since most of them are not justified and would be completely useless to other classes), yet you have a getter and setter for every single one of them.
If you do have a lot of getter and setter, put them at the end, this stops having to scroll 20 minutes to access any of the actual implementation in the class.

Here is how I would have probably written the StudentTable Class.

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

public class StudentTablePanel extends JPanel {

private static JTable table;

public StudentTablePanel() {
table = createTable(getStudentList()); // This line—in my opinion—makes it more immediately understandable what is happening, you're creating a table from a list of students.
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
add(scrollPane);
}

// Reading "Students.txt" file and adding students to the "studentList" ArrayList.
public ArrayList<Students> getStudentList() {
ArrayList<Students> list = new ArrayList<>();
try (Scanner scanner = new Scanner(new URL("http://rawsly.com/Students.txt").openStream())) { // Try with resources loop automatically closes the scanner when done
while (scanner.hasNext()) {
String name = scanner.next();
String lastName = scanner.next();
long studentId = scanner.nextLong();
double quiz1 = scanner.nextDouble();
double quiz2 = scanner.nextDouble();
double project = scanner.nextDouble();
double midterm = scanner.nextDouble();
double finalGrade = scanner.nextDouble();
double average = scanner.nextDouble();
String letterGrade = scanner.next();
list.add(new Students(name, lastName, studentId, quiz1, quiz2, project, midterm, finalGrade, average, letterGrade));
}
} catch (IOException ex) {
// Handle your exception
}
return list;
}

public JTable createTable(ArrayList<Students> studentList) {
String[] columnNames = {"NAME", "SURNAME", "ID", "QUIZ1", "QUIZ2", "PROJECT", "MIDTERM", "FINAL", "AVERAGE", "LETTER GRADE"};
int row = studentList.size();
int column = columnNames.length;
Object[][] data = new Object[row][column];
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
switch (j) {
case 0:
data[i][0] = studentList.get(i).getName();
break;
case 1:
data[i][1] = studentList.get(i).getLastName();
break;
case 2:
data[i][2] = studentList.get(i).getStudentId();
break;
case 3:
data[i][3] = studentList.get(i).getQuiz1();
break;
case 4:
data[i][4] = studentList.get(i).getQuiz2();
break;
case 5:
data[i][5] = studentList.get(i).getProject();
break;
case 6:
data[i][6] = studentList.get(i).getMidterm();
break;
case 7:
data[i][7] = studentList.get(i).getFinalGrade();
break;
case 8:
data[i][8] = studentList.get(i).getAverage();
break;
case 9:
data[i][9] = studentList.get(i).getLetterGrade();
} // end of the switch
} // end of the first for loop
} // end of the second for loop

JTable newTable= new JTable(data, columnNames) {
@Override
public boolean isCellEditable(int row, int column) { // To make row and columns not editable
return false;
}
};
newTable.setFillsViewportHeight(true);
newTable.setAutoCreateRowSorter(true); // to activate sorting property of each column

return newTable;
}
}

Tabed pane with a label on top

Here is a quick example to use JLayer(as suggested by mKorbel):

import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;

public class TopRightCornerLabelLayerUITest {
public static JComponent makeUI() {
JTabbedPane tab = new JTabbedPane();
tab.addTab("New tab1", new JLabel("1"));
tab.addTab("New Tab2", new JLabel("2"));
JPanel p = new JPanel(new BorderLayout());
p.add(new JLayer<JComponent>(tab, new TopRightCornerLabelLayerUI()));
return p;
}
private static void createAndShowUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
createAndShowUI();
}
});
}
}
class TopRightCornerLabelLayerUI extends LayerUI<JComponent> {
private JLabel l = new JLabel("A Label at right corner");
private JPanel rubberStamp = new JPanel();
@Override public void paint(Graphics g, JComponent c) {
super.paint(g, c);
Dimension d = l.getPreferredSize();
int x = c.getWidth() - d.width - 5;
SwingUtilities.paintComponent(g, l, rubberStamp, x, 2, d.width, d.height);
}
}


Related Topics



Leave a reply



Submit