I am refactoring my code. I have a JPanel:
public JPanel createLayout() {
log.info("create Layout");
JPanel panel = new JPanel();
panel.add(TestTable());
return panel;
}
I want to add TestTable to this panel. My TestTable looks like that:
public void TestTable() {
JLabel lFxRates = new JLabel("FXRates");
//get data
try {
stm = new SettingsTableModel(settingsService.getTestByParameter("DebtService"));
stm.setColumnNames(fxColumnNames);
} catch (Exception e) {
new HelperFunctions().showError("Error loading data!" + e);
}
fxTable = new JTable(stm);
fxTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
return null;
}
The problem I am facing is that nothing gets shown, because of return null. To which thing can I add my table to add it later to my JPanel?
I really appreciate your answer!
You have the problem that you are adding nothing, like null.
Everything you add to the panel must inherit from the parent- class called Component.
So, your Class TestTable, i hope it is a Class, must inherit from JTable or so.
instead of "return null", try adding "return fxTable".
In panel.add(TestTable()), TestTable() is expecting the component.
Related
I am learning Java Swing. I am trying to develop as simple app for learning purpose. There is are multiple issues in following code. I try to read a csv file and populate JComboBox on button click.
public class MyForm {
private JButton btnRead;
private JButton btnRead2;
private JComboBox cbCodes;
private JPanel mainPanel;
private DefaultComboBoxModel comboBoxModel;
public MyForm(){
// issue 1: I always get null pointer exception in this line
comboBoxModel = new DefaultComboBoxModel();
cbCodes = new JComboBox(comboBoxModel);
btnRead.addActionListener( e -> {
List<String[]> data = readData();
comboBoxModel.removeAllElements();
data.forEach(item -> comboBoxModel.addElement(item));
});
// issue 2: Since DefaultComboBoxModel was not working. I tried without it. As this I get correct data in the array. But when I make JComboBox with array. Nothing is filled. It is empty.
btnRead2.addActionListener( e -> {
List<String[]> data = readData();
String[] array = new String[data.size()];
data.toArray(array);
cbCodes = new JComboBox(array);
});
}
// issue 3: I can't complie the code without this empty method. Why do I need it?
// error: Form contains components with Custom Create option but no createUIComponents() method
void createUIComponents(){
}
public List<String[]> readData() {
String file = "data.csv";
List<String[]> content = new ArrayList<>();
try(BufferedReader br = new BufferedReader(new FileReader(file))) {
String line = "";
while ((line = br.readLine()) != null) {
if(line.contains("\"")){
content.add(line.split(" "));
}
content.add(line.split(","));
}
} catch (FileNotFoundException e) {
//Some error logging
} catch (IOException e) {
e.printStackTrace();
}
return content;
}
public static void main(String[] args) {
JFrame frame = new JFrame("MyForm");
frame.setContentPane(new MyForm().mainPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
I make my question in the source code with the comment to show exactly here those issues are involved.
You don't get the NullPointerException in the lines you indicated, but in the line btnRead.addActionListener( e -> { because btnRead has not been initialized yet!
When you create a new JComboBox, you have to add it to the panel, too. Just creating it with new will not display it. But the real problem behind it is: you're using the model wrong. Write
comboBoxModel.removeAllElements();
for (final String string : array) {
comboBoxModel.addElement(string);
}
to solve that.
The problem you have here does not lie within the code you provided, but from another component. At some point, someone used a UI designer. Those designers usually create initialization methods, just like createUIComponents. See where that method gets called.
Synopsis:
All in all, your code is really chaotic. Restructure from new, this will clean up a lot of problems.
And initialize UI components as soon as possible, best do it in the declaration line: private final JButton btnRead = new JButton("Read!");
I strongly recommend using an IDE like Eclipse or IntelliJ that will help you write clean code and see and correct problems easier.
I'm currently working on a game that's based on a client-server architecture. What basically happens is that one player can create a lobby that others can connect to by providing IP address and port number (so, actually basic Java Sockets). Before the actual game is started, all players are first placed inside a lobby which consists of a JLabel displaying the player count and a JTextArea providing information about people joining or leaving the lobby. Everytime a new player connects or someone leaves the lobby, the host pushes out notifications to the clients for updating their UI correspondingly.
The problem is now the following: I want the lobby to be displayable in fullscreen if the user likes (which is also implemented already using keybindings/Input-/Actionmaps). However, when a user changes from window to fullscreen or back the current frame has to be disposed and as a consequence reset to the initial lobby state. I originally wanted to solve this using the class LobbyState which stores all relevant data to be restored. However, somehow this is not working as the frame still displays the initial state of the lobby when changing "window-mode".
To give you an insight into the code, this is the relevant code of the Lobby class:
private int playerCount = 1;
private boolean isHost;
public Lobby(Integer windowState, Image image, Boolean isHost, LobbyState lobbyState) {
this.isHost = isHost;
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("Lobby");
setExtendedState(MAXIMIZED_BOTH);
setSize(screenDim);
setMinimumSize(new Dimension(800, 400));
setIconImage(image);
if (windowState == 1) {
setUndecorated(true);
} else {
setUndecorated(false);
}
setResizable(true);
contentPane.setLayout(null);
setLayout(null);
contentPane.getInputMap(KeyBindings.AFC).put(KeyStroke.getKeyStroke("F11"), "lobby_fullscreen");
contentPane.getActionMap().put("lobby_fullscreen", new EnterFullscreen(this, this.isHost, new LobbyState(playerCount, getLobbyHistory())));
contentPane.setBackground(new Color(253, 205, 136));
setContentPane(contentPane);
loadComponents();
loadBounds();
addActionListeners();
if (lobbyState != null) {
lblPlayerCount.setText("" + lobbyState.getPlayerCount());
txtLobbyHistory.setText(lobbyState.getLobbyHistory());
}
setVisible(true);
}
My first assumption why F11 triggers the creation of a Lobby with the initial state instead of the current state is, that the ActionMap is created when playerCount is still 1 and getLobbyHistory() doesn't return anything because there actually still is no lobby history. If this is really the problem, is there any possibility to tell the ActionMap to re-read the values of playerCount and getLobbyHistory() whenever F11 is pressed? Would I have to remove the current ActionMap and add a new one or is there a more elegant way to solve this?
In case this is of any interest, this is the code that currently performs the toggle between window and fullscreen application:
public class EnterFullscreen extends AbstractAction{
private static final long serialVersionUID = 1773898497666165938L;
private JFrame frame;
private boolean isHost;
private LobbyState lobbyState;
private Class<?> frameType;
private Constructor<?> c;
public EnterFullscreen(JFrame frame, boolean isHost, LobbyState lobbyState) {
this.frame = frame;
this.isHost = isHost;
this.lobbyState = lobbyState;
try {
frameType = frame.getClass();
if (frameType.equals(Lobby.class)) {
c = frameType.getConstructor(Integer.class, Image.class, Boolean.class, LobbyState.class);
} else {
c = frameType.getConstructor(Integer.class, Image.class, Boolean.class);
}
} catch (SecurityException | NoSuchMethodException e) {
e.printStackTrace();
}
}
#Override
public void actionPerformed(ActionEvent e) {
try {
frame.setVisible(false);
if (frame.isUndecorated()) {
if (frameType.equals(Lobby.class)) {
c.newInstance(0, frame.getIconImage(), isHost, lobbyState);
} else {
c.newInstance(0, frame.getIconImage(), isHost);
}
} else {
if (frameType.equals(Lobby.class)) {
c.newInstance(1, frame.getIconImage(), isHost, lobbyState);
} else {
c.newInstance(1, frame.getIconImage(), isHost);
}
}
frame.dispose();
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException e1) {
e1.printStackTrace();
}
}
}
I'd really appreciate any input on how to solve this and how one would achieve something like this properly. If you feel like there's any missing information or code to solve this, please let me know and I'll try to provide that as soon as possible.
Why can't I call the setModal() method?
I am working on GUI. I have two jframes. The following code is for a button and is supposed to open the other frame. But i get error that says:
cannot find method setModal(boolean)
private void jButton3_actionPerformed(ActionEvent e)
{
HR hr = new HR();
if(f == 1){ // condition
hr.setModal(true); // give me error here ?
hr.setVisible(true);
}else{
jLabel5.setText("You aren't connected...");
}
}
hr.java
import java.awt.Dimension;
import javax.swing.JFrame;
public class HR extends JFrame {
public HR() {
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}
private void jbInit() throws Exception {
this.getContentPane().setLayout( null );
this.setSize( new Dimension(400, 300) );
}
}
I am working on GUI I have two jframes
An application should only have a single parent JFrame. Other child windows should be a JDialog and you specify the frame as the parent.
A JDialog DOES have the setModal(...) method.
You create a JDialog the same way you create a JFrame.
JFrame class has no setModal(boolean) method..
refer to the doc here
therefore you CAN NOT invoke that method, your HR class must instead have defined that method... but I see in the update that actually the HR class is not defining it...
I'm writing a holiday recommendation system for a piece of coursework. The GUI of which uses CardLayout. In the main class a user object is created with default name and access levels defined in it's constructor. this object is passed from main to the UserCard panel which passes it to Login and logged in.
if the user successfully logs in then the cardpanel transitions from Login to logged in and is supposed to display the username of the logged in user by calling the user.getUsername(); method.
my problem is thus. because of the way card layout works the panel with the username display has already been created in the constructor of UserCards with the default values from then the user object was first created. I need to find a way to force this panel to repaint after the show method is called on the cardlayout object. The following is the code of the 3 classes in question. (I've limited the code paste to the relevant methods).
//the usercards panel
public UserCards(User u)
{
CardLayout cl = new CardLayout();
this.setLayout(cl);
UserOptionsPanel options_card = new UserOptionsPanel(cl, this);
RegisterPanel register_card = new RegisterPanel(cl, this);
LoggedInPanel loggedin_card = new LoggedInPanel(cl, this, u);
LoginPanel login_card = new LoginPanel(cl, this, u, loggedin_card);
this.add(options_card, options);
this.add(login_card, login);
this.add(register_card, register);
this.add(loggedin_card, loggedin);
}
//the Loggin action listener user is passed in as a reference to the user object created in //main. the createUser(); method is a badly named method that simply calls setter methods on //the user object's fields
#Override
public void actionPerformed(ActionEvent e)
{
String[] vals = packData();
try
{
DBConnection d = new DBConnection();
Connection conn = d.getConnection();
Validation v = new Validation(vals, user);
v.getActual(conn);
if(v.validate())
{
user = v.createUser();
System.out.println(user.getUserName());
l.revalidate();
cl.show(pane, "loggedin");
}
else
{
lbl_statusmsg.setText("Password Incorrect");
lbl_statusmsg.repaint();
}
}
catch(ClassNotFoundException | SQLException ex)
{
ex.printStackTrace();
}
}
//the loggedin constructor
public class LoggedInPanel extends JPanel
{
private User user;
private JLabel lbl_details;
public LoggedInPanel(CardLayout cl, Container pane, User u)
{
super();
user = u;
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
lbl_details = new JLabel();
lbl_details.setText("Welcome "+user.getUserName());
this.add(lbl_details);
}
}
Apologies if I've not been overly clear I'm not given to asking for help :)
Do you mean something like ?
CardLayout cl = new CardLayout() {
#Override
public void show(java.awt.Container parent, String name) {
super.show(parent, name);
// your code here
}
};
Can someone tell me, where is my mistake?
I'm trying to fill up table with data but I can't, always get empty table.
Here is my code with frame:
import java.util.*;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class Rinktis extends JFrame {
private final JScrollPane scrollPane = new JScrollPane();
private JTable table;
public Rinktis()
{
super();
setBounds(100, 100, 861, 375);
try {
jbInit();
} catch (Throwable e) {
e.printStackTrace();
}
}
Vector<Vector<String>> data1 =new Vector<Vector<String>>();
Vector<String> heading1 = new Vector<String>();
public void tab(Vector heading, Vector data)
{ System.out.println(data);
System.out.println(heading);
data1=data;
heading1=heading;
System.out.println(data1);
System.out.println(heading1);
}
private void jbInit() throws Exception {
getContentPane().setLayout(null);
getContentPane().add(scrollPane);
scrollPane.setBounds(10, 10, 825, 176);
table = new JTable(data1,heading1);
scrollPane.setViewportView(table);
}
}
Here's how I call it from another frame:
protected void rinktisButton_1_actionPerformed(ActionEvent e)
{ Rinktis frame = new Rinktis();
frame.setVisible(true);
try {
db.getClients();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
and from db.getClients(); I call rinktis.tab(columnHeads,v);
System.out.println gives me all data correctly, but table is empty.
change your tab function to be like this:
public void tab(Vector heading, Vector data)
{
table.setModel(new DefaultTableModel(data,heading) );
}
For a serius answer you need to post an SSCCE. Anyway it seems that you are passing a wrong type to JTable constructor.
You need to pass a 2d array of object (Object [][]) or Vector<Vector<Object>> not plain 1D Vector, same as for TableHeader
I think here's the problem :
table = new JTable(data1, heading1);
//data1 need to of type Object[][] or Vector<Vector<Object>>
//heading1 need to of type String[] or Vector<String>
Here's a tutorial.
The problem is that the table does not know that you changed the data. You can either load your data on creation of the table. Then it should show up just fine (maybe try this out first). Then in a second step you should work directly with the tablemodel and change data there. Whenever you do so call the you can notify the table to update.
Alternatively, if you already know your header, you can set it and only add the data later. This also should work. However I do not recommend this.