Unable to resize JButton - java

I'm Stuck with how to resize the third button to became the same size like the other two and place it on the bottom.
class ControlFrame extends JFrame
implements Runnable
{
JButton jb_inc = new JButton();
JButton jb_zero = new JButton();
JButton jb_dec = new JButton();
ControlFrame() {
super("Control Frame");
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
ControlFrame(int x,int y, int w, int h) {
this();
this.setBounds(x, y, w, h);
this.setVisible(true);
jb_inc.setBounds(10,10,90,20);
jb_zero.setBounds(10,40,90,20);
jb_dec.setBounds(10,60,90,20);
jb_inc.setVisible(true);
jb_zero.setVisible(true);
jb_dec.setVisible(true);
this.getContentPane().add(jb_inc);
this.getContentPane().add(jb_zero);
this.getContentPane().add(jb_dec);
}
public void run() {
}
}
public class Counting_Machine
{
public static void main(String[] args) {
ControlFrame cf = new ControlFrame(0,200,80,150);
}
}

I suggest you start by reading the section from the Swing tutorial on Using Layout ManagersYour code won't work because you are trying to add 3 components to the "center" of the BorderLayout which won't work. Choose a LayoutManager that better meets your needs.
There is no need to use the setBounds(...) method when using a layout manager. The job of the layout manager is position the components based on the rules of the layout manager. The preferred size of each button should be the same since you have not added any text to the buttons.
Also, there is not need to invoke setVisible() on the buttons, all Swing components are visible by default, except the top level containers (JFrame, JDialog).

Two suggestions:
1) put common things into the instance initialization block. Personally I shudder whenever I see a call to "this()".
{
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
ControlFrame()
{
super("Control Frame");
}
ControlFrame(int x,int y, int w, int h)
{
super("Control Frame");
...
}
2) I would get rid of the x, y, w, h constructor... personally I have a class called WindowUtils that has a "position" method that figures out the screen size and then uses the values passed in to create a window that is the relative size of the screen. Then the code that creates the window calls that. I prefer to have as few constructors as possible (very often that is zero or one, I hardly ever have two or more).
3) this.getContentPane().add(jb_inc); can now be written as add(jb_inc); - since JDK 1.5 I think.
4) never call overrideable methods (all the things you have this. before) inside the constructor. If a subclass were to override "add" you could see things break. So you can call super.add(), or do the adds in another method, or make your class final.
Now to answer your question... :-)
You need to make use of LayoutManagers to get what you want.
Depending on what you want you probably want to use a BorderLayout so you can get the button on the bottom.

Since you're setting bounds on everything, you don't need a LayoutManager at all. Set your LayoutManager to null, then you can position everything yourself, as you are in your example.
this.setLayoutManager(null)

Related

Changing a JLabel's position

After a lot of research I only could get that board image with using label. Now I cannot change it's position. I tried a lot of functions. What is the exact function do I need
public class Board extends JFrame {
private ImageIcon image;
private JLabel label;
public Board() {
image = new ImageIcon(getClass().getResource("board.png"));
label = new JLabel(image);
label.setLocation(200, 0); //This is the one that I expected to do the thing
add(label);
}
public static void main(String [] args) {
Board b = new Board();
b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
b.setVisible(true);
b.setSize(1280, 1000);
}
}
Don't try to manually set the location of a component. Swing was designed to be used with layout managers. Read the section from the Swing tutorial on Using Layout Managers for more information.
One way to position a component is to give the component a Border. So you could do something like:
label.setBorder( new EmptyBorder(200, 0, 0, 0) );
The tutorial also has a section on How to Use Borders.
First of all: you shouldn't move components manually. This should be left to the layoutmanager. But you can. The basic problem you're facing is - or atleast i think so - : you're board still has an layoutmanager set, which will continue to layout the board and due to this aswell move (and handle the size of) you're component. Just call setLayout(null); before positioning the label and specify the size and it should work.

My own JButton preferred size is not working correctly?

If I want to create my own custom JButton and i want to set the preferred size how do I go about doing this. I thought that it might be easy but when I get to it I have a dimension that I will be sending into my preferred size.
But then how do I set the correct x, y, width, and height values for my specific JButton component. It seems redundant to just call setPreferredSize again from in side of the same method?
This is the thing that I find odd about overriding a JComponent. I see how they are supposed to work with the paintComponent(...).
I want my new button to have a preferred size (is this the default size) that is 20 x 20.
I want to set this on any button were the size is not set by the constructor.
Also what methods should be overridden when creating a custom button?
class myButton extends JButton {
public myButton(String s) {
super(s);
}
public void setPrefferedSize(Dimension d) {
this.setBounds(x, y, width, height)
setPreferredSize(d);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.RED);
}
}
First of all: Adding an #Override annotation to your setPrefferedSize method would have made clear that it should be called setPreferredSize.
Apart from that, the getPreferredSize and setPreferredSize methods have some special semantics in a JComponent. Quoting from the JComponent#getPreferredSize documentation:
If the preferredSize has been set to a non-null value just returns it. If the UI delegate's getPreferredSize method returns a non null value then return that; otherwise defer to the component's layout manager.
When setting the preferred size with setPreferredSize, everything is fine. (I'd not recommend to create a subclass of a component only to call some set... methods in the constructor, but I assume that you'll have some additional methods that will justify extending the class).
However, when overriding getPreferredSize of JComponent, one should try to preserve the semantics of this method. That means that you should rather override it like that
#Override
public Dimension getPreferredSize()
{
// If the preferred size was set manually, return this
// size in order to be in line with the specification
// that is described in the JavaDoc
if (super.isPreferredSizeSet())
{
return super.getPreferredSize();
}
// Otherwise, return "your" preferred size. The
// DEFAULT_WIDTH and DEFAULT_HEIGHT would be 20,20
// in your case
return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
(actually, one would have to first ask the UI for a preferred size, but this is probably not desired here)
Try overriding getMaximumSize and getMinimumSize. Which value is used and how they are used depends on the layout (and its implementation). Setting all three (min, max, preferred) should get you a definite size if the layout doesn't misbehave.
call super.setPreferredSize(d); inside overridden setPrefferedSize() method otherwise it will result in StackOverflowError calling same method again and again.
Try with overridden getPreferredSize() method for your custom JButton class.
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 20);
}
It's really very simple.
public class MyButton extends JButton {
public MyButton(String s) {
super(s);
this.setPreferredSize(new Dimension(20, 14));
this.setBackground(Color.black);
this.setFont( new Font("Verdana", Font.BOLD, 10));
this.setForeground(Color.WHITE);
}
}
It's not redundant to use the methods to set something predefined, it's how your supposed to do it. What would be redundant would be doing this on 24+ buttons in your program, cluttering your guy constructor up with code it doesn't need to have.

Simple animations in Java

I'm attempting to code a simple animation or physics example in a Java Swing application. I have the actual windows application open and working, but I can't figure out how to actually draw my shapes, and how I'd format the code for calculations between frames, that sort of stuff.
I've read some stuff about over riding a paint method, but I don't know what that means, and I don't believe I'm using it in the code I'm using right now. This is my code:
public class Physics extends JFrame{
public Physics() {
initUI();
}
private void initUI() {
JPanel panel = new JPanel();
getContentPane().add(panel);
panel.setLayout(null);
final JLabel label = new JLabel("Hi, press the button to do something");
label.setBounds(20, 0, 2000, 60);
final JButton submitButton = new JButton("Start");
submitButton.setBounds(20, 150, 80, 20);
submitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//Put button code here later
}
});
panel.add(label);
panel.add(submitButton);
setTitle("Program");
setSize(300, 250);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Physics ex = new Physics();
ex.setVisible(true);
}
});
}
}
So I have some blank space above my button where I'd like to draw maybe a square or circle moving across the screen to start off with, once I get that down I can start getting into the more advanced stuff. Any hints on how to do that would be appriciated :D
Thanks!
"I've read some stuff about over riding a paint method, but I don't know what that means"
So you've overridden actionPerformed, so you know what an #Override is. As you'll notice from the ActionListener, you never actually explicitly call actionPerformed, but whatever you put in the there, still get's used. That's because the ActionListener implicitly call it for you.
The same is true with painting. In the Swing painting process, there is a paint chain that Swing uses to paint components. Along the way paint is called somewhere. So just like actionPerformed, you can override paint and it will get implicitly called for you.
#Override
public void paint(Graphics g) {
super.paint(g);
}
The Graphics object passed to the method is the graphics context that Swing will use for the painting. You can look at the Graphics API to see the methods you can use. You can use drawOval to draw a circle
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawOval(x, y, width, height);
}
Now here's the thing. You don't actually want to override paint. In the tutorials linked above, some of the examples will use applets and override paint, but you shouldn'y paint on top level containers like JFrame or JApplet. Instead paint on a JPanel or JComponent and just add it the JFrame. When you do paint on JPanel or JComponent, you'll instead override paintComponent (which also gets called along the paint chain), instead of paint
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(x, y, width, height);
}
You see how I used variables for the drawOval method. The x is the x location from the top-let of the screen, and y and the y point. width and height are width and height of the circle. The great thing about using variables is that their values can be changed at runtime.
That's where the animation comes to play. As pointed out, you an use a javax.swing.Timer
The basic construct is
public Timer(int delay, ActionListener listener) {
}
The delay is the milliseconds to delay each call to the listener. The listener will have your actionPerformed call back that will do what's inside, every delay milliseconds. So what you can do, is just change the x from the drawOval and repaint(), and it will animate. Something like
Timer timer = new Timer(40, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
x += 5;
repaint();
}
});
timer.start();
The timer code you can just put in the constructor. That's probably simplest explanation I can give. Hope it helps.
Don't forget the to see Custom Painting and Grapics2D for more advance topics on graphics. Also see some example of timers and animation here and here and here and here and here
Also avoid using null layouts. See Laying out Components Within a Container to learn how to use layout managers, as should be done with Swing apps.
Take a look at the Swing tutorial on Custom Painting.
The example shows you how to do painting. If you want animation, then you would use a Swing Timer to schedule the animation. The tutorial also has a section on How to use a Swing Timer.
Put the two tutorial together and you have a solution.
There are any number of ways to achieve this.
Start by taking a look at:
Performing Custom Painting
2D Graphics
For details about how painting in Swing is done.
Animation is not as simple as just pausing a small period of time and then repainting, theres acceleration and deceleration and other concepts that need to be considered.
While you could write your own, that's not a small task, a better solution might be to use a pre-existing engine, for example...
Then take a look at:
Timing Framework
Trident
java-universal-tween-engine
Which are all examples of animation engines in Swing. While I prefer the Timing Framework as it provides me with a lower level API, this is a personal opinion. Both Trident and the JUWE seem to be geared more towards component/property based animation (which the Timing Framework can do if you want to build some of the feature sets up)
I created a simple animation with two rockets blasting off. The full eclipse project is here: https://github.com/CoachEd/JavaExamples/tree/master/RaceToSpace. Here's a screenshot:

Saving JPanel Graphics

I'm not quite sure exactly how Graphics work in Java so I having trouble debugging my problem.
I have a Class MyFrame Extends JPanel. Now I do some drawing on MyFrame save and save me properties about that certain frame then add it an ArrayList collection of MyFrames. Later on I want to recall the properties a certain instance of MyFrame and repaint that frame on the screen. Having the the graphic of frame show up again is what I am having trouble with.
Here is a quick bit of code that will demonstrate my problem.
public class MyFrame extends JPanel{
private int property;
private int x;
private int y;
public MyFrame(int xp, int yp){
x = xp;
y = yp;
}
#override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.fillRect(x,y,5,5);
}
public void setProperty(int p){
property = p;
}
}
public class MainClass() extends JPanel{
private ArrayList<MyFrame> frames = new ArrayList<MyFrame>;
private MyFrame currentFrame = new MyFrame();
public void addFrame(int x, int y){
this.remove(currentFrame);
currentFrame = new MyFrame();
this.add(currentFrame);
frames.add(currentFrame);
}
public void setFrame(int frame){
this.remove(currentFrame);
currentFrame = frames.get(frame);
this.add(currentFrame);
}
}
Summary:
I'd like the panel to display the correct frame when setFrame is called. currently when I do this set frame will be blank.
You seem to be swapping JPanels in and out of another JPanel, and when doing this, you must take into consideration the layout used by the container-JPanel and you would need to call revalidate and repaint on the container-JPanel after the swap.
But rather than mess with all of this, why not go the easy route by just swaping JPanels or perhaps JLabels with ImageIcons holding an image using a CardLayout?
You could also consider adding some states, an enum data member, to a single JPanel and ask it to switch from one state to another, then call its repaint method and, in its paintComponent overriden method, draw some graphics according to its state.
Your architecture (as enhance by #Hovercraft Full of Eels is also good, even better if the draw methods vary quite a lot and have very different purposes. However, my proposal could lay to a faster app, and could allow other fatures such as transition between states, shared double buffer, variable/code reuse in case graphics are close.
What is your app doing ?
Regards,
Stéphane

Redrawing graphics in Java

I'm just getting into graphics in Java and I have a problem. I created a JFrame window (NetBeans Designer) with a JPanel panel and I drew some graphics on it. Then I added a JButton that changed a variable, which would change the X position of a square on JPanel.
On button press this code would execute:
drawObject.setX(150);
drawObject.repaint();
drawObject is an instance of this class:
public class sola extends JPanel {
private int x = 10;
#Override
public void paintComponent(Graphics g){
super.paintComponents(g);
super.setBackground(Color.WHITE);
g.setColor(Color.ORANGE);
g.fill3DRect(x, 160, 100, 50, true);
}
public void setX(int xX){
x = xX;
}
}
Now, when I press the JButton, the rectangle does move to the new position, however it is still visible in the old position. Only when i resize the window does it refresh and the old rectangle disappears. How can i solve this problem, so that when i press the button, the rectangle is only visible in the new position?
It's
super.paintComponent(g);
not
super.paintComponents(g); // note the s at the edn
Big difference between the two! The first one tells your JPanel to do all the housekeeping functions normally performed by the paintComponent method, including repainting the background (key for your project). The second, the one your calling doesn't do any of the above functionality. So my advice is to get rid of the trailing s in your super call.
You can use the following methods from JComponent: ( http://download.oracle.com/javase/6/docs/api/javax/swing/JComponent.html )
void repaint(long tm, int x, int y, int width, int height)
Adds the specified region to the dirty region list if the component is showing.
void repaint(Rectangle r)
Adds the specified region to the dirty region list if the component is showing.
You can call those before redraw()
You could use repaint() method to do tis.
If you use the paintComponent() on the panel. You should IMHO take care of the painting in the whole panel. There is no code in your example which takes care about deleting the old painted rectangles.
What i recommend is creating an own Component for your rectangles. (You could extend from Component) then you can override the paintComponent method of these classes as you did in your panel. Because the Panel should act as a container component. Not as drawing the rectangles itsself.
Know add instances of these components to a normal JPanel. This should then update as expected.

Categories