I can't figure out how to make the following code work. When you press a jbutton I want it to run the following code. My problem is that the ArrayList list is located in the main and I don't know how to pass it into this method provided to me by the GUI builder so that, that actionperformed method will know what list is and return an ArrayList back to the main to replace it with the new changes.
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Student temp;
Picker pick = new Picker(list);
temp = pick.randomNoReplace(); //replace randomNoReplace() with radio button choice
list.remove(temp); //the next line must be temp.increaseScore() or temp.decreaseScore() or neither
list.add(temp);
}
}
What you are looking for is something like this:
class Foo {
private ArrayList<Student> list;
...
This will declare list as an ArrayList of Students as an instance variable so that each object of this class can access list from any instance method. Just be sure to instantiate list before using it, preferably inside your constructor doing something like this:
list = new ArrayList<Student>();
Related
I am programming an application that deals with orders from a database. It has several pages, a navigation, a header that always should show information about the actual order you are working with and a content area, in which the details of said order get shown:
My MainProgram extends a JFrame and contains a CardLayout, in which the other pages are hosted, so when the user clicks on the page in the navigation, only the view of the content-area changes. Logo, header and the navigation stay the same. The header keeps displaying the order number.
As there are several different pages that contain details about the same order, I need to "send / transfer" information about the order from one page to the other so I can show some information in the header and in the content area from the order object.
But I am not getting this to work as intended, mostly to my misunderstand of static and when to use it, where objects get created exactly and also the complexity of my program: I am using a class that is intended for the navigation and therefore should also handle
the information transfer from one page to the other.
Since I am using a database, creating a MVCE will be hard, so instead I will show the important parts of my program.
MainProgram.java
Here the navigation and the content panel (centerPanel) get created, also the CardLayout. centerPanel and the CardLayout are static, so I can call this from other classes and switch the page that is shown (probably not a good idea?):
NavigationPanel navigationPanel = new NavigationPanel();
public static JPanel centerPanel = new JPanel();
public static CardLayout contentCardsLayout = new CardLayout();
I create the pages and put them into my CardLayout:
OverviewPage overviewPage = new OverviewPage();
BasicDataPage basicDataPage = new BasicDataPage();
centerPanel.setLayout(contentCardsLayout);
overviewPage.setName("overviewPage");
basicDataPage.setName("basicDataPage");
centerPanel.add(overviewPage, "overviewPage");
centerPanel.add(basicDataPage, "basicDataPage");
The main method, where I create a MainProgram object:
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
The overview page contains a JTable which gets populated from a database. If the user double-clicks an entry, he gets transfered to the BasicDataPage where he can see the details of the order.
But in order to show the details, I need to somehow transfer the information of the order object into the target class and thats the point I am struggling with!
// I tried several things like object into constructor, static object, creating a method etc...
if (mouseEvent.getClickCount() == 2 && row != -1) {
String workNumberOfOrderObject = (String) table.getValueAt(row, 0);
OrderObject orderObject = GetOrderObject.getOrderObjectFromDatabase(workNumberOfOrderObject);
BasicDataPage basicDataPage = new BasicDataPage();
basicDataPage.recieveOrderObject(orderObject);
workNumberPanel.recieveOrderObject(orderObject);
workNumberPanel.setTxtWorkNumber(workNumberOfOrderObject);
MainProgram.contentCardsLayout.show(MainProgram.centerPanel, "basicDataPage");
}
I tried "sending" the order object to the BasicDataPage via the constructor and set the text in the JTextFields in the BasicDataPage accordingly. This did not work, the textfields simply stayed empty altough I can System.out.println(orderObject.toString()) the recieved object.
BasicDataPage.java
I also tried creating a method receiveOrderObject that I use in the OverviewPage, which should set the textfields of the basicDataPage AND the workNumberPanel, but the fields stay empty:
WorkNumberPanel workNumberPanel = new WorkNumberPanel();
JTextField txtCarWidth = new JTextField(TEXTFIELD_LENGTH);
JTextField txtCarDepth = new JTextField(TEXTFIELD_LENGTH);
JTextField txtCarHeight = new JTextField(TEXTFIELD_LENGTH);
public void recieveOrderObject(OrderObject orderObject){
txtCarDepth.setText(orderObject.getCar_depth());
}
Before posting my question I've read several Q/As here on SO like this:
Accessing UUID from another class in Java ... suggesting to use static for global variables.
I know that static variables are class variables, that all instances can use and only one version exists of. So I tried to send a static object from one class to the other.
But since I am using JTextFields, I had to mix static and non-static content, which either did not work at all or the textfields disappeared.
I have the feeling that I am getting a very basic concept in java wrong, so any help, no matter in which direction, is appreciated!
EDIT:
Based on Reşit Dönüks answer, I was able to fill the textfields by making BasicDataPage and loadBasicData(orderObject) in MainProgram static. Now I can do MainProgram.loadBasicData(orderObject); ... and the textfields in the BasicDataPage get filled as intended.
Is this a valid approach or do I get problems for using static for GUI-Elements? ..... Don't!
I realized that, your are creating BasicDataPage in each double click.
if (mouseEvent.getClickCount() == 2 && row != -1) {
String workNumberOfOrderObject = (String) table.getValueAt(row, 0);
OrderObject orderObject = GetOrderObject.getOrderObjectFromDatabase(workNumberOfOrderObject);
BasicDataPage basicDataPage = new BasicDataPage();
This is the main problem. Do not create BasicDataPage there, just reach the created instance and set the order object to that. My solution is below.
public class MainProgram implements OrderView{
//remove statics here
private JPanel centerPanel = new JPanel();
private CardLayout contentCardsLayout = new CardLayout();
private BasicDataPage basicPage;
public MainProgram() {
//other codes
OverviewPage overviewPage = new OverviewPage();
basicPage = new BasicDataPage();
centerPanel.setLayout(contentCardsLayout);
overviewPage.setName("overviewPage");
basicDataPage.setName("basicDataPage");
centerPanel.add(overviewPage, "overviewPage");
centerPanel.add(basicPage, "basicDataPage");
//oher codes
}
#Override
public void loadOrder(OrderObject order) {
basicPage.recieveOrderObject(orderObject);
contentCardsLayout.show(centerPanel, "basicDataPage");
}
}
public interface OrderView {
public void loadOrder(OrderObject order);
}
public class OverviewPage {
OrderView orderView;
public OverviewPage(OrderView orderView) {
this.orderView = orderView;
}
//in ActionPerformed
if (mouseEvent.getClickCount() == 2 && row != -1) {
String workNumberOfOrderObject = (String) table.getValueAt(row, 0);
OrderObject orderObject = GetOrderObject.getOrderObjectFromDatabase(workNumberOfOrderObject);
orderView.loadOrder(orderObject);
workNumberPanel.recieveOrderObject(orderObject);
workNumberPanel.setTxtWorkNumber(workNumberOfOrderObject);
}
}
As pointed already, Singleton is the way to go. I would just like to point out a mistake in the code provided in the answer before.
private static MainFrameinstance = null;
Rename MainFrameinstance to instance or vice-versa; because the same variable is checked by the getInstance() method.
I have a quick question. I don't get it...
I've got a JFrame where I add a JComboBox:
JComboBox<String> Team_ComboBox = new JComboBox<>();
Team_ComboBox_Handler ComboBox_Listener = new Team_ComboBox_Handler();
Team_ComboBox.addActionListener(ComboBox_Listener);
Team_ComboBox.addItem("Test 1");
Team_ComboBox.addItem("Test 2");
On this Frame I have a button which opens another JFrame.
Play = new JButton();
Play.setText("Play");
Play.setPreferredSize(dimension);
Play.addActionListener(menuhandler);
private class main_menuhandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==Play){
teams Team = new teams();
Team.teams();
disposeMainMenue();
}
if(e.getSource()==Close) {
System.exit(DO_NOTHING_ON_CLOSE);
}
}
}
Anyway, I would like to transfer the Selected value of the Combobox to a method of the other class. I know how I can get the itemvalue of the combobox in the method itself (with getselecteditem) But how can I do that in the ActionPerformed Method as I can't access the combobox in the ActionPerformed method.... I created another ActionListener (comboBox_Listener) but I haven't put any code into it...
Any idea? Thanks a lot in advance
Several issues appear to me:
Your main question:
But how can I do that in the ActionPerformed Method as I can't access the combobox in the ActionPerformed method
Your likely best solution is to change your code and variable declaration placement so that you can access the JComboBox fromt he actionPerformed method. If you're declaring the combobox from within a method or constructor, change this so that it is a proper instance field of the class.
Other problems:
You should not be creating multiple JFrames. If you need a dependent window, then one should be a JDialog. If not, then consider swapping views with a CardLayout.
Learn and follow Java naming conventnions so others can better understand your code. Class names begin with capital letters and methods and variable names don't for instance.
I am not sure why you're doing this: System.exit(DO_NOTHING_ON_CLOSE);. Why pass that constant into the exit method?
Use a constructor for your action listener class:
private class main_menuhandler implements ActionListener {
private JComboBox<String> Team_ComboBox;
public main_menuhandler(JComboBox<String> Team_ComboBox){
this.Team_ComboBox = Team_ComboBox;
}
}
Now you can create the class main_menuhandlervia the constructor and add the combobox to it.
In your Overriden action you have access to it.
Try playing around with this as your code snippet isn't broad enough to actually provide proper code. But this should answer your question
first of all I will introduce what I am trying to do. This is an assignment in university we are making Hotel booking system with JAVA. To go straight to the point, all I need to know is how to update JList when I press button.
listModel = new DefaultListModel<Hotel>();
bookingList = new JList(listModel);
class MouseAdapterMod extends MouseAdapter {
public void mousePressed(MouseEvent e) {
if(e.getSource() == searchButton){
for(lists.getRoomsList() p : lists.getRoomsList())
{
listModel.addElement(p);
}
bookingList.setModel(listModel);
}
In this GUI class I have instance variable (lists) of Hotel class, in Hotel class there are methods
public ArrayList<Rooms> getRoomsList()
{
return roomsList.getListRooms();
}
public ArrayList<Suite> getSuitesList()
{
return roomsList.getListSuites();
}
this returns whole ArrayList of Room class objects and also ArrayList of Suite class.
QUESTION would be is how to show whole ArrayList of Rooms when I press button, in other words how to update JList which consists of objects, by pressing button?
I hope I explained alright.
Your for-each loop is wrong. Try this and see:
public void mousePressed(MouseEvent e) {
if(e.getSource().equals(searchButton)){
ArrayList<Rooms> rooms = lists.getRoomsList();
for(Rooms r : rooms) {
listModel.addElement(r);
}
bookingList.setModel(listModel);
}
}
This still looks sorta messy to me though. A more appropriate approach would be to set an event handler on the searchButton, to populate the JList when searchButton is clicked.
Also, are Rooms and Suites sub classes of Hotel? If not, you'll have to create listModel like this (for rooms):
listModel = new DefaultListModel<Rooms>();
My program is based on a API. I got a JList with and a model that has a some names. And a selectListener to get the seleted item and a button to send that item to the other window which has another Here is my first list:
First List (window) and send the items to the other list.
final DefaultListModel<String> Names = new DefaultListModel<String>();
final JList<MyAPI> Places = new JList(Names);
private JList<MyAPI> locList;
private DefaultListModel<MyAPI> favourites;
public AddLocation(JList<MyAPI> locList, DefaultListModel<MyAPI> favourites){
this.locList = locList;
this.favourites = favourites;
}
addThis.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
Object chose = Places.getSelectedValue();
favourites.addElement((MyAPI) chose); // error in this line
}
});
And this is the other window that selected items should be added to here:
final DefaultListModel<MyAPI> favourites;
final JList<MyAPI> locList;
favourites = new DefaultListModel<MyAPI>();
locList = new JList<MyAPI>(favourites);
So now both windows loads and the first list loads with its names in it. but when I press the button add this, it gives error and points to this line:
favourites.addElement((MyAPI) chose);
How can I solve it?
Your first model is defined like this:
final DefaultListModel<String> Names ...;
Your second model is defined like this:
final DefaultListModel<MyAPI> favourites;
Your first list model conains String instances, your second model contains MyAPI instances. So when this line is executed:
favourites.addElement((MyAPI) chose);
you are trying to make a MyAPI out of a String, which does not work and probably a ClassCastException is thrown.
Either you need to declare the second list model as final DefaultListModel<String> favourites; or you create an instance of MyAPI based on the selected String (new MyAPI(chose) ?).
Found solution
decided it was easier to simply make a method outside of the actionListener called chairPrice which can be incremented by a method called getItemPrice(). This has been used to calculate the total price of items and works 100%
You need to use the Object.equals() method.
#Override
public void actionPerformed(ActionEvent buttonClick)
{
if(buttonClick.getSource().equals(guiButtons[0])) //if user clicks on 'add chair'
{
Chair chair = new Chair();
}
}
Edit in response to the OP's comment
I'm not exactly sure what you're wanting. myChair isn't the name of your chair. It's the name of the variable. It has no effect on Chair at all. If you want to make a new Chair object and have it available for the whole class, you're going to need to either add a new field variable or make a list of Chair.
public class GuiClass extends JPanel implements ActionListener
{
List<Chair> chairs = new ArrayList<Chair>(Arrays.asList(new Chair()));
Desk myDesk = new Desk();
Table myTable = new Table();
#Override
public void actionPerformed(ActionEvent buttonClick)
{
if(buttonClick.getSource().equals(guiButtons[0])) //if user clicks on 'add chair'
{
chairs.add(new Chair());
}
}
}