Java Swing - Why JComponent won't display? - java

I'm trying to extend a class to eventually make a custom button. I read in several places that it's best to extend as high as possible on the heirarchy (for better polymorphism?), so I'm trying to extend JComponent:
import javax.swing.*;
import java.awt.*;
public class TestButton extends JComponent {
private static final long serialVersionUID = 1L;
public TestButton() {
super();
}
}
And the code that calls this is:
b1 = new TestButton();
basePanel.add(b1,gbc); // (gbc is GridBagConstraints object)
The thing is, my JComponent isn't displayed in my layout. If I extend the class as JButton, it shows no problem. What's the deal?
Update:
FYI, this is sort of a noob conceptual question, I'm far from proficient here obviously.
Here's a picture to describe. The only thing changed is extends ______.
What should be happening is a purple-filled block, the same height as the yellow block on the bottom.
What is happening is a default sized block that has no background (the black is from the JFrame).

One of the main differences between JComponent and it's subclasses is that the latter have UI delegates, while JComponent does not. Note that the setBackground() "color is used only if the component is opaque, and only by subclasses of JComponent or ComponentUI implementations." As a result, you "must override paintComponent() to honor this property."

What do you expect to see in the place where JComponent is supposed to be? when you extend JButton, you get all its graphic with it, but you created an empty component, with nothing in it. Try putting something in the component (such as a JLabel or similar)

You still need to extends JButton if you want JButton's functionality. Otherwise everybody can extend Object and expect everything.

It is a blank component (basically a template). It has no properties. You have to add your own graphical elements by overriding the paintComponent method and then add logical elements by overriding the update method.

Either use the JButton as it is:
JButton b1 = new JButton("Enter JButton text here");
basePanel.add(b1,gbc);
or extend the JButton class if you wish to change certain properties and customize it for your own preferences:
public class TestButton extends JButton {
private static final long serialVersionUID = 1L;
public TestButton(String buttonText)
{
super(buttonText);
}
}

Related

JButton global settings

So I have created multiple JButtons in my app. Now I want to modify their design, like, change color, size, style, etc. Is there any way to avoid having to set these things to every JButton separately?
Custom Class that extends JButton
As already suggested, you can use a custom class that extends JButton change the styling of the button there, and then create instances from this custom class.
An example:
import javax.swing.*;
import java.awt.*;
public class CustomJButton extends JButton
{
private Font font = new Font("MS UI Gothic", Font.BOLD, 30);;
public CustomJButton(String buttonName)
{
this.setText(buttonName);
this.setFont(font);
this.setForeground(Color.BLUE);
}
}
You then create an instance of this class in your main class like this:
.
.
CustomJButton button = new CustomJButton("Click Me");
.
.
And you have as a result:
Alternative solution
You can use the Font object to declare "global" settings.
An example:
Font font = new Font("MS UI Gothic", Font.BOLD, 30);
And lets assume that you have the following jButtons: jButton1, jButton2:
jButton1.setFont(font);
jButton2.setFont(font);
The font class as can be seen from the above link it doesn't include color attribute, unfortunately, but an easy fix, is to declare a global Color object lets say: Color colorButton = Color.BLUE that you can later use to set the color to all the buttons.
This becomes useful when you want to change the color of the buttons, you just have to change one line of code, and will affect all the buttons.
Conclusion
Both solutions may solve your problem, but, in my opinion, implementing your custom class that extends JButton is the way to go, as your code will look much clear and straightforward.

Getting text from a JTextArea using a JButton and a JTabbedPane

Newbie here trying to make a simple GUI with JTabbedPane. I've looked through a lot of examples but have been unable to find a solution. Basically, I'm trying to print out a String to a JTextArea. While it seems very simple, I have been unable to get everything to work together. I understand the difference between local and global variables, but I think that is where my problem lies. Any guidance would be greatly appreciated. *Please note that we are unable to use a layout manager for this project.
The code below represents part of the tab that has the JButton and JTextArea.
//Text area that shows details. Scrolls.
JTextArea areaDeets = new JTextArea();
areaDeets.setBounds(65, 300, 250, 300 );
areaDeets.setText("");
JScrollPane scroll = new JScrollPane (areaDeets);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
panel2.add(areaDeets);
panel2.add(scroll);
areaDeets.addActionListener(new StopTest());
//Stop button--stops tests when pressed.
JButton stop = new JButton("Stop");
stop.setBounds(215, 650, 100, 40);
panel2.add(stop);
stop.addActionListener(new StopTest());
The code below is the method that calls the ActionListener.
//Panel 1 - Stop, shows that the test has been stopped
static class StopTest implements ActionListener{
public void actionPerformed(ActionEvent e){
String stop = "The test has been stopped";
areaDeets.setText(stop);
panel2.repaint();
}
}
Edit: Code does not compile. Eclipse says that I cannot call addActionListener on a JTextField.
You can pass the reference of the JTextArea to the constructor of the ActionListener:
public class StopTest implements ActionListener {
private JTextArea area;
public StopTest(JTextArea area) {
this.area = area;
}
public void actionPerformed(ActionEvent e) {
String stop = "The test has been stopped";
area.setText(stop);
}
}
One possible solution (guessing here due to limited information): don't make the StopTest class static. Rather make it a private inner non-static class or a stand-alone class. This will allow it access to non-static fields of your outer class.
Don't add an ActionListener to your JTextArea as this is not allowed and has no real meaning, since JTextAreas allow returns to be entered, and use this to start a new line in the JTextArea.
Other unrelated recommendations:
Also, as a general rule, you should avoid use of null layout as this makes for very inflexible GUI's that while they might look good on one platform look terrible on most other platforms or screen resolutions and that are very difficult to update and maintain.
Much better would be to use nested JPanels, each using its own layout manager, and then calling pack() on your JFrame after adding all components but prior to displaying it.
Never call setBounds(), setSize(), setPreferredSize() or any similar call on a JTextArea that goes inside of a JScrollPane as it will prevent the JScrollPane from working correctly within your JScrollPane due to your setting bounds. This will prevent the JTextArea from expanding when more lines are added, sometimes preventing display of the scrollbars, or if their displayed, preventing them from working properly. Better to set the JTextArea's viewable columns and rows via one of its constructors that has int parameters.
There's no need to call repaint() after setting the text of a JTextComponent such as a JTextArea, since the textarea's model will notify its view (the part that is rendered on the GUI) of changes, and the view will then automatically call repaint itself.

How to inherit addActionListener to custom object?

I have 2 classes, one is an instanceof JPanel (called xContain) and the other isn't extending anything (called xShape). There is way too much code to paste here and I don't want to be spoon fed, so I'm going to carefully explain it.
I'm trying to call .addActionListener() on an instance of my xShape. However, it won't work since it doesn't have that method. However, this works when I do it to an instance of JButton or Timer object and I found out that's because the method is inherited from class javax.swing.AbstractButton.
What do I have to inherit to my xShape class so I can add an action listener to it?
If your class is supposed to work as a button or menu (as #HovercraftFullOfEels mentioned), then you can declare your class to inherit from AbstractButton:
public class Test extends AbstractButton
and override the addActionListener method:
#Override
public void addActionListener(ActionListener l)
{
super.addActionListener(l);
// ...
}
Edit:
The imports you need are:
import java.awt.event.ActionListener;
import javax.swing.AbstractButton;
ActionListeners are for button and menu type objects. If your class is neither of these, then don't try to force a square peg into a round hole.
Instead consider using a MouseListener, not an ActionListener, adding the MouseListener to the container that is displaying your XShape, and make sure that your XShape class has a contains(Point p) method. This way you can have objects of the type check if button press points are contained within them, and thus react.

Communictating between classes using Jpanel, repaint() method

I have a class "GUI" that extends JPanel. I have another class "Buttons" that extends JFrame. I'm trying to have the JFrame class call a method "clearScreen()" in the JPanel class when the when a JButton "clearB" is pushed on the JFrame.
The only way I could make this work was by building the object for the JPanel class "GUI" right in the actionlistener for the JButton:
clearB.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
GUI g = new GUI();
g.clearScreen();
}
}
);
But then when I called the method clearScreen(), which looks like this:
public void clearScreen(){
xs.clear();
ys.clear();
count = 0;
repaint();
}
NOTHING HAPPENED. I'm guessing it's because the repaint() method wasn't working for some reason unknown to me.
Someone PLEASE show me an easier, working way of doing what I'm trying to accomplish here.
Thanks! :D
The reason that your ActionListener isn't working is because the GUI object that you create in there is a new GUI object, one that is completely unrelated to the GUI object that is displayed, and so calling the clearScreen() method on the non-displayed GUI instance will have no effect on the displayed GUI instance.
The solution is for your Buttons class to hold a valid reference to the visualized GUI object and call methods on this reference. The reference can be passed via a setter method or constructor parameter.
i.e.,
public class Buttons {
private GUI gui;
public Buttons (GUI gui) {
this.gui = gui;
}
// in some ActionListener code...
gui.someMethod();
}
A couple of comments:
It is unusual that you should have to have a class that extends JFrame. Myself, I try to avoid doing this unless necessary, but rather usually create my JFrames from the JFrame class itself, and only when needed.
I'm a little surprised that your main window class doesn't already have a GUI variable, since it likely displays the GUI instance.

Transitions between JPanel?

First of all... I'd like to say that I am not interested in using the card layout for this... Unless it's necessary (which means that not using the card layout would be result in unnecessary workarounds and complex code). This is for learning purposes after all and I will look into the card layout very soon enough anyway...
Okay so my question is pretty basic GUI layout I guess. My code is not working and this whole layouting confuses me quite a lot...
I'm having trouble how to make the transition between JPanels like this:
I have one window. I press a button, the old window is replaced by another window. I press a button and that window will be replaced by another window.
I'd like to add that I am skipping a lot of irrelevant code in my example below...
I start off with a JFrame:
public class StartWindow extends JFrame{
public StartWindow(){
//Add JButton & ActionListener
//When the button is pressed:
add(new NextWindow());
}
public static void main(String [] args){
new StartWindow();
}
}
then I have several JPanels...
public class NextWindow extends JPanel{
public NextWindow(){
//Add a JButton & ActionListener
//When the button is pressed:
add(new NextWindow2());
remove(this);
//This does not work. Nothing happens.
}
}
public class NextWindow2 extends JPanel{ // Stuff and so on}
So, I'd like to know a proper way to handle this situation!
You are adding a panel to itself. You need to remove the panel from the JFrame, add the new one to it, and call revalidate() on the JFrame.

Categories

Resources