Hi i basically have two classes,
one main and one just to separate the panels, just for code readability really.
i have :
public class Main{
public static void main (String args[]) {
JFrame mainJFrame;
mainJFrame = new JFrame();
//some other code here
CenterPanel centerPanel = new CenterPanel();
centerPanel.renderPanel();
mainFrame.add(centerPanel.getGUI());
}
}
class CenterPanel{
JPanel center = new JPanel();
public void renderPanel(){
JButton enterButton = new JButton("enter");
JButton exitButton = new JButton("exit");
center.add(exitButton);
center.add(enterButton);
}
public JComponent getGUI(){
return center;
}
}
Above code works perfectly. It renders the centerPanel which contains the buttons enter and exit. My question is:
I still need to manipulate the buttons in the main, like change color, add some action listener and the likes. But i cannot access them anymore in the main because technically they are from a different class, and therefore in the main, centerPanel is another object.
How do I access the buttons and use it (sets, actionlisteners, etc)? even if they came from another class and i still wish to use it inside the main?Many Thanks!
Make the buttons members of CenterPanel
class CenterPanel{
JPanel center = new JPanel();
JButton enterButton;
JButton exitButton;
public void renderPanel(){
enterButton = new JButton("enter");
exitButton = new JButton("exit");
center.add(exitButton);
center.add(enterButton);
}
public JButton getEnterButton()
{
return enterButton;
}
public JButton getExitButton()
{
return exitButton;
}
public JComponent getGUI(){
return center;
}
}
You have reference to centerPanel in your main method. After you invoke centerPanel.renderPanel();
the buttons will be added to the 'center' reference of type JPanel in CenterPanel instance. You can get the reference of 'center' by invoking centerPanel.getGUI(); in main method.This will return the center reference of type JComponent. JComponent is a awt container.so, you can call center.getComponents(). This will return all the components in an array present in the JPanel. i.e. center reference. You can iterate them, get their type and do whatever you want.
Related
I am trying the build a GUI, I have a set of radio buttons and I want a slider to show only when a specific radio button is pressed
I have set the visibility of the panel which contains the slider to false, but I can't reach that panel outside of AddVehicleDialog class (because it is a local variable of that class) and I need access for it in MyActionListener class.
I tried using getRootPane() to get the panel which the slider was added to, but it returned null.
//AddVehicleDialog.java class
public class AddVehicleDialog extends JDialog {
// All of the addVehicleDialog buttons, radio buttons and sliders
JButton okButton, cancelButton;
static JRadioButton redButton, grnButton, whtButton, svrButton;
static JRadioButton benzineCar, solarCar, bikeRadButton, carriageRadButton;
JSlider gearsSlider;
public AddVehicleDialog() {
setTitle("Add a vehicle to the city");
setLayout(new BorderLayout());
setSize(550, 300);
setResizable(false);
setLocationRelativeTo(null);
setModal(true);
// OK & Cancel buttons & radio buttons
addVehicleDialogButtons();
}
//bike's gears slider - part of addVehicleDialogButtons() method;
gearsSlider = new JSlider(0, 10);
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new BorderLayout());
JLabel gearsLabel = new JLabel("Choose bike's gears");
gearsLabel.setHorizontalAlignment(JLabel.CENTER);
gearsLabel.setVerticalAlignment(JLabel.CENTER);
centerPanel.add(gearsLabel);
gearsSlider.setMajorTickSpacing(2);
gearsSlider.setMinorTickSpacing(1);
gearsSlider.setPaintTicks(true);
gearsSlider.setPaintLabels(true);
gearsSlider.setExtent(0);
centerPanel.add(gearsSlider,BorderLayout.SOUTH);
centerPanel.setVisible(false);
this.add(centerPanel,BorderLayout.CENTER);
//MyActionListener class is in a different file from centerPanel component
public class MyActionListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
.
.
.
case "OK":
if (AddVehicleDialog.bikeRadButton.isSelected()) {
//this is what i want to do
centerPanel.setVisible(true);
}
I know I can't reach centerPanel, because it is a local variable of AddVehicleDialog class.
I've made the gearsSlider static so I could reach him in MyActionListener class
I don't think it is a good practice to put centerPanel as static, but I can't think of other way to reach this specific panel outside of the class.
I hope it is understandable enough. If more clarification is needed, please tell and I'll provide.
The panel when visibility set to false:
The way I want the panel to look when I select Bike radio button.
The first popup would only send one action, the second would send two, third will be three so and so forth. I was able to narrow it down to it being the button sending action multiple time.
At first, I was using jframe for all my window, so I tried using jdialog, the problem persists. tried making it so that when the user clicks on the button the window is disposed, still don't fix it.
public class BoothDetails extends JDialog implements ActionListener{
FloorPlanGUI floorPlan = new FloorPlanGUI();
static JLabel bname = new JLabel();
JTextArea details = new JTextArea();
static JButton addsche = new JButton("ADD TO SCHEDULE");
JPanel northPanel = new JPanel();
public BoothDetails(String name, String detail) {
setVisible(true);
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
bname.setText(name);
details.setText(detail);
setLayout(new BorderLayout());
northPanel.setLayout(new FlowLayout(0, 10, 10));
northPanel.add(bname);
northPanel.add(addsche);
addsche.addActionListener(floorPlan);
addsche.addActionListener(this);
add(northPanel, BorderLayout.NORTH);
add(details, BorderLayout.CENTER);
}
public void actionPerformed(ActionEvent a) {
dispose();
}
}
static JLabel bname = new JLabel();
JTextArea details = new JTextArea();
static JButton addsche = new JButton("ADD TO SCHEDULE");
Don't use the static keyword. This means the variable is shared by all instances of the class.
So every time you create a new instance of the class you execute the following code:
addsche.addActionListener(floorPlan);
which adds another ActionListener to the button.
The static keyword is should generally only be used when you create constant variables in your class, it should NOT be used for components which need to be unique for each class.
I have a JFrame which contains 3 JPanels (each in a separate class). The first JPanel contains two JTextFields in which I write the name of the file to be read from and the condition to be fulfilled respectively. This doesn't really affect my question, so let's move on.
The second JPanel has a JTextArea.
The third JPanel has two JButtons (Load, Sort) which are supposed to load a list of entries that suffice the condition from the first JPanel and then reorganize them according to some rules (respectively).
THE PROBLEM:
Ok so, the first class is the JFrame class in which i just do the standard look and feel of the window.
The second class is the first JPanel with two JTextFields.
I won't give code for this one because the second JPanel code is shorter and has the same problem so I imagine that the same solution would apply.
Third class contains the JTextArea in which I should display certain entries from the text-file.
Code:
public class SecondPanel extends JPanel {
JPanel panel;
JTextArea lista;
public SecondPanel() {
panel = new JPanel();
list = new JTextArea("List");
list.setPreferredSize(new Dimension(200, 150));
this.add(list);
}
}
Moving on, the fourth class contains the Jbuttons and the ActionListener(Button listener). Ok so here is the part of the code from the button listener class
CODE:
private class ButtonListener implements ActionListener {
SecondPanel secondPanel = new SecondPanel();
FirstPanel firstPanel = new FirstPanel();
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("Load")) {
//calls method that loads data from the text in a firstPanel field
loadData(firstPanel.theFile.getText());
for(int i = 0; i< students.length; i++) {
if(students[i]!=null) {
// doesn't write anything tried with .setText etc.
secondPanel.list.append(students[i]+"\n");
}
}
}
}
}
So the program won't get text when i type in the JTextField designated for the file path. And when i do it manually in the code, It won't write the changes to the list on the Window (JTextArea). But when i System.out.print to the console it prints the changes and lists entries correctly as well as any setText changes I make. It just won't write or read to and from the Window..
What should I do?
The problem is that you are calling your setText methods on the wrong objects.
In your listener class, you declared two new panels as class variables, and then you call your methods on them, but i think those panels are not the ones you really want to change.
You should first add your panels to your Jframe object, and refer to them on your ActionListener.
Here i provide you a minimal code which modifies a JTextArea when a JButton is pressed. (same for a JTextField)
import java.awt.*;
import javax.swing.*;
public class MyJFrame extends JFrame {
SecondPanel sPanel;
public MyJFrame() {
super("main");
Container c = getContentPane();
c.setLayout(new BorderLayout());
JButton button = new JButton("load");
button.addActionListener(new LoadListener());
c.add(sPanel = new SecondPanel(), BorderLayout.NORTH);
c.add(button, BorderLayout.SOUTH);
pack();
setVisible(true);
}
class SecondPanel extends JPanel {
public JTextArea list;
public SecondPanel() {
super();
list = new JTextArea("List");
list.setPreferredSize(new Dimension(200, 150));
add(list);
}
}
class LoadListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
sPanel.list.setText("new text for the jtext area");
}
}
public static void main(String[] args) {
new MyJFrame();
}
}
I copied all of the relevant code below, and my problem is that after running the action performed (which is connected to a button) the values I tried to change in the action performed didn't actually change.
I put a sout(ques) at the end of the action performed and I can see the change in value but when I move outside of it, it reverts back to the 0;
public class GameRunner extends JPanel implements ActionListener{
private int x=50,y=600;
private Ball b = new Ball(x,y);
private Timer timer;
private boolean correct , incorrect;
private JButton button;
private JTextField f;
private int ques = 0;
private String[][] math = {{"2X^2","4x"},{"q2","a2"},{"q3","a3"},{"q4","a4"},{"q5","a5"},
{"q6","a6"},{"q7","a7"},{"q8","a8"}};
public void actionPerformed(ActionEvent actionEvent) {
if (f.getText().equals(math[ques][1])) {
correct = true;
} else {
incorrect = true;
}
f.setText("");
if(ques<7)
ques++;
else
ques = 0;
System.out.println(ques);
//I can see the change here
}
public void paint(Graphics g){//called whenever refreshed...
System.out.println(ques);
// But now outside of the action performed the ques and the correct incorrect do not change
if(correct)
b.move();
if(incorrect)
b.move2();
}
public static void main(String[] args) {
GameRunner gui = new GameRunner ();
gui.go();
}
public void go(){
button = new JButton("Guess");
f = new JTextField(15);
button.addActionListener(this);
JFrame frame = new JFrame("Derivative Game");
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(700, 700));
JPanel pan = new JPanel(new BorderLayout());
JPanel pan2 = new GameRunner();
JPanel pan3 = new JPanel();
pan3.add( f);
pan3.add(button);
pan3.setBackground(new Color(80, 218, 213));
pan.add( pan3,BorderLayout.CENTER);
pan.setBackground(new Color(80, 218, 213));
frame.add(pan2);
frame.getContentPane().add(BorderLayout.SOUTH, pan);
frame.setSize(700, 760);
frame.setVisible(true);
frame.setResizable(false);
}
}
The basic problem is that you've actually got two instances of GameRunner here: the one you create in main(), and another one that you add to the JFrame. Since you only call go() on the one not in the JFrame, that instance's paint() method will never be called.
You need to refactor your code to eliminate that second stray GameRunner instance. While you're at it, you should also use paintComponent() instead of paint(), and you should take any "business logic" (like those calls to move()) out of your painting code.
In other words, get rid of this line:
JPanel pan2 = new GameRunner();
Since you're already "in" an instance of GameRunner, you shouldn't be creating another one. Then to use the "current" instance of GameRunner, you can use the this keyword:
frame.add(this);
Edit- You also aren't telling your GameRunner JPanel to repaint itself after the button is clicked. You might want to add a call to repaint() in your actionPerformed() method.
In my question, this is Refectoring Class. In this class, i'm using JPanel for adding button by a separate Method panel() and Call in the RefectClass Constactor.
public class RefectClass extends JFrame {
JButton btnHome,btnBack;
JPanel btnContainer;
public RefectClass(){
super("Title Here");
setSize(350,300);
add(this.panel(),BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public void panel(){
btnContainer=new JPanel();
btnHome=new JButton("Home");
btnBack=new JButton("Back");
btnContainer.add(btnHome);
btnContainer.add(btnBack);
}
}
Now how to add panel to JFrame? it gives an error, when i try to use it. I'm unable use to the panel() Mehtod.
Your panel() method returns void - it should return your newly created JPanel instead such that you can add it to the JFrame:
public JPanel panel(){
btnContainer=new JPanel();
btnHome=new JButton("Home");
btnBack=new JButton("Back");
btnContainer.add(btnHome);
btnContainer.add(btnBack);
return btnContainer;
}
Let me point out, though, that this is a very unusual approach. You shouldn't have to initialize a member in a public method that returns the newly initialized member when the method is actually just needed inside the class. Imagine a client calling the panel method multiple times from outside (since it is public). BtnContainer, btnHOme and BtnBack would be overriden but they wouldn't appear on the screen.
The method seems fairy simply - why not just include it directly in your constructor?
Or at least make the method private.
Your panel() method doesn't return anything so you can't write
add(this.panel(),BorderLayout.CENTER);
try
this.panel();
add(this.btnContainer,BorderLayout.CENTER);