java applet buttons - java

OK so I have this applet thats like this
BorderLayout.CENTER - (Within this is JPanel)
BorderLayout.EAST - (Within this is a new GridLayout (4,5)
BorderLayout.SOUTH - (Within this is a TextArea)
Anyway, on the applet, I have to HOVER over the buttons to see them. They don't paint there I guess but I'm adding them in the init() method... so I don't know what I am doing wrong and why it's doing this.
setLayout( new BorderLayout() );
JPanel invOne = new JPanel(new GridLayout(5,4));
JPanel game = new JPanel();
add(invOne, BorderLayout.EAST);
add(game, BorderLayout.CENTER);
add(c, BorderLayout.SOUTH);
invOne.setBounds(416,0, 60, 28);
for (int i = 0, j = 20; i < 20; i = i+1, j = j-1) {
invOne.add(new JButton("SLOT " + j));
invOne.setBounds(32,32,100,100);
invOne.setFocusable(false);
}
game.setBounds(0,0, 416, 288);
repaint();

What are you trying to accomplish with all the setBounds() calls? Either you let pack() set your panel's size according to what's inside, or you set bounds once to where you want to see that panel sit. Especially the calls with a size of 32x32 pixels are not helping at all.
EDIT:
I found these problems:
As one other poster mentioned, you're mixing Swing and AWT components. That doesn't work well. Essentially, if some of the components you use have a "J" at the beginning, you'll want to go with "J"'s for all of them. AWT is now considered "old school". It's a bit confusing because some classes and components used in GUIs don't have J's. I guess you need to work carefully with good examples or look the classes up.
For some reason, the applet didn't want to work well until I gave explicit row/column counts to the TextArea (now called JTextArea). I changed new TextArea() to new JTextArea(3,20).
The biggest problem may have been the empty paint() method. I wonder how the applet displayed anything at all? You could have removed the paint() method; I fixed it by calling super.paint().
Finally, class names (such as bl) should start with uppercase characters. The compiler in IdeOne grumbled at me for that.
Here's my fixed code.
Happy hacking!

Found one page (in german language) which describes the same problem: JButton widgets only show up after hovering over them.
The problem there was that AWT and Swing components/widgets have been mixed. I can't see from your code fragment if this is the case, but if you have java.awt.* imports, disable them, refactor your code to only use Swing classes and try again / hope for the best.
Another suggestion was to explicitely do a setVisible(true) for every button, but the questioner said, that this didn't help in his case.

After adding all your components in the panel, do you explicitely call the "pack()" (or the "repaint()") method ?
Not calling theses methods can result in graphic troubles in your Frames...

You are using Swing components in an Applet. You should use JApplet. Just change extends Applet to extends JApplet.

Related

Centering Java JPanel Elements [duplicate]

I have a panel derived from JPanel. I have a custom control derived from JLabel. I am attempting to center this custom JLabel on my panel.
The only way I know to do this that will work is to use the a null layout (setLayout(null)) and then calculate the custom JLabel's setLocation() point so that it's in the right spot.
The custom JLabel is physically moved from one panel to this panel in this app and I believe the location previously set in setLocation is affecting things. However when I set it to (0,0) the component goes up into the upper left corner.
BorderLayout doesn't work because when only 1 component is provided and placed into BorderLayout.CENTER, the central section expands to fill all of the space.
An example I cut and pasted from another site used BoxLayout and component.setAlignmentX(Component.CENTER_ALIGNMENT). This didn't work either.
Another answer mentioned overriding the panel's getInset() function (I think that's what it was called), but that proved to be a dead end.
So far I'm working with a panel with a GridBagLayout layout and I include a GridBagConstraints object when I insert the custom JLabel into my panel. This is inefficient, though. Is there a better way to center the JLabel in my JPanel?
Set GridBagLayout for JPanel, put JLabel without any GridBagConstraints to the JPanel, JLabel will be centered
example
import java.awt.*;
import javax.swing.*;
public class CenteredJLabel {
private JFrame frame = new JFrame("Test");
private JPanel panel = new JPanel();
private JLabel label = new JLabel("CenteredJLabel");
public CenteredJLabel() {
panel.setLayout(new GridBagLayout());
panel.add(label);
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(panel);
frame.setSize(400, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
CenteredJLabel centeredJLabel = new CenteredJLabel();
}
});
}
}
Supose your JLabel is called label, then use:
label.setHorizontalAlignment(JLabel.CENTER);
Forget all the LayoutManagers in the Java Standard Library and use MigLayout. In my experience it's much easier to work with an usually does exactly what you expect it to do.
Here's how to accomplish what you're after using MigLayout.
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class Test
{
public static void main( String[] args )
{
JFrame frame = new JFrame( );
JPanel panel = new JPanel( );
// use MigLayout
panel.setLayout( new MigLayout( ) );
// add the panel to the frame
frame.add( panel );
// create the label
JLabel label = new JLabel( "Text" );
// give the label MigLayout constraints
panel.add( label, "push, align center" );
// show the frame
frame.setSize( 400, 400 );
frame.setVisible( true );
}
}
Most of that is just boilerplate. The key is the layout constraint: "push, align center":
align center tells MigLayout to place the JLabel in the center of its grid cell.
push tells MigLayout to expand the grid cell to fill available space.
BoxLayout is the way to go. If you set up a X_AXIS BoxLayout, try adding horizontal glues before and after the component:
panel.add(Box.createHorizontalGlue());
panel.add(label);
panel.add(Box.createHorizontalGlue());
I don't like the answers here.
I've never seen a valid use of a GridBagLayout ever in my career. Not saying there isn't one, just saying I haven't seen [a valid] one, and there might be correlation there. Moreover, adding a single JLabel to the middle of a Container might make it center for demonstrational purposes, but you're going to have a lot harder of a time later on if you try to continue to work with that over some other layouts.
I do like the suggestion about the BoxLayout, because that is actually a great way to do it. That said, that answer is only part of the puzzle, hence why I'm dredging up a 7 year old question.
My 'Answer'
Really there is no short answer to your question. There is an exact answer to your question based on what you asked, but StackOverflow is about a community learning from each other, and I suspect you're trying to learn how to use layouts in general (or you were 7 years ago) and telling you to type a combination of keys to do exactly your demo case is not going to teach you the answer.
I'm going to try not to explain any layouts that you can't web-search the answer for on your own (with a link to the Oracle tutorial at the end, because I think it explains the different layouts fairly well).
BoxLayout
BoxLayout is one way to do it, and there is already a code snippet to demo it above so I won't provide one. I'll expand on it to say that, just as mentioned, that only answers your question exactly, but doesn't really teach you anything. Glue, as the BoxLayout refers to it, basically gives you an equal amount of remaining real-estate between all the 'glue' currently in the Container. So, if you were to do something like
panel.add(Box.createHorizontalGlue());
panel.add(label);
panel.add(Box.createHorizontalGlue());
panel.add(otherLabel);
You would find that your JLabel is no longer centered, because the 'glue' is only the remaining real-estate left, after two JLabels were added to the Container which will be equally divided between the two 'slots' (two calls to Container#add(Component) with a glue parameter) in theContainer`.
BorderLayout
BorderLayout is another way to go about this. BorderLayout is broken down into 5 regions. BorderLayout#CENTER, as you might guess, is the center region. The important note about this layout and how it centers things is how it obeys sizes of the Component that is in the center. That I won't detail though; the Oracle tutorial at the end covers it well enough if you're interested, I think.
Worth Noting
I suppose you could use a GridLayout, but it's a more simple way to do it over a GridBagLayout, which I already said even that I think is not a good approach. So I won't detail this one either.
The Point of it All
Now all that said, I think all LayoutManagers are worth a look. Just like anything else with relation to programming - use the tool that fits the job. Don't just assume because you used X layout before, that you should always use X layout and no other layout is viable. Figure out what you want your display to look like, and how you think it should behave with respect to resizing components, and then pick what you think would work best.
Another dual meaning of picking the right tool, is that you don't have to just fit all of your components into one single Container and make one layout do everything. There is nothing stopping you (and I strongly encourage you to) use multiple Containers and group them all together. Control each Container with a layout that is appropriate for that section of the display, and a different layout for a different Container.
Important!!
The reason why this is very important is because each layout has rules and things that they obey, and other things that they respect, and then others that are effectively ignored (i.e. preferred, maximum, and minimum sizes, for instance). If you use different layouts [correctly], you will find your display accepts dynamically being resized while still obeying the shape that you wanted it to hold. This is a very important key difference between doing it the right way, and just settling with GridBagLayout.
JPanel outer = new JPanel(new BorderLayout());
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.PAGE_AXIS));
JPanel southPanel = new JPanel(new CardLayout());
outer.add(centerPanel, BorderLayout.CENTER);
outer.add(southPanel, BorderLayout.SOUTH);
Figure out what is appropriate to your scenario, and go with that. There is no one-size-fits-all unless you want something overly cumbersome and made redundant by other layouts (i.e. GridBagLayout).
Oracle's Tutorial
If you've made it this far, then I think you're looking for as much information as you can get. In which case, I strongly encourage you to read Oracle's tutorial on layout managers because it lays out general details of them all very well: https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
Use this.
labelName.setHorizontalAlignment(SwingConstants.CENTER);
or
labelName.setHorizontalAlignment(JPanel.CENTER);
Both of them must work.
Do like this instead of libraries and layouts :
JLabel jlabel = new JLabel("Label Text", SwingConstants.CENTER);
Make sure to import javax.swing.SwingConstants INTERFACE , BUT DO NOT IMPLEMENT IT. It contains only constants and no methods.
Put the JLabel in a JPanel or else it will come at the center of the JFrame or JWindow (your top level container).

java JLayeredPane how to add JPanel in front of another panel generated by Window builder

I am writing in java some kind of application and i have to place something in front of another objects( in Z order)
I know that that i should use JLayeredPane but in fact i am not very familiar with it.
My idea is to make two JPanel's with different Z-order factors while inserting them to JLayeredPane.
i pasted my code http://www.wklejto.pl/130038
i would be very grateful if you tell me what is wrong because i am doing it for a long of time with no effect.
I don't see anything wrong with this code. Maybe you're trying to paint a transparent (not opaque) JPanel (e.g. with message) on top of the underlying base JPanel.
In that case you should invoke setOpaque(false) on your front JPanel.
JPanel second = new JPanel();
second.setOpaque(false);
second.add(new JLabel("message"));
jlp.add(second, new Integer(300));
JPanels are opaque by default - on the other hand JLabels aren't.
And take a look into tutorial.

Can't add component to JPanel in Swing

I want to add at runtime a JLabel under the purple pane which contains already some components, say under the progress bar:
Here is the structure of the elements:
And this is my code which is issued when an event occurs (it's getting there i checked with debug) :
jPanel1.add(new JLabel("Stack Overflow"));
jPanel1.revalidate();
jPanel3.revalidate();
I'm not seeing any changes whatsoever and have no clue where to go from here. When i put a
textarea in the purple pane and then call it's setText() method at the same place i try to add the JLabel component it works.
You need to learn more about layouts and how they work. I strongly suggest you read the entire layout manager tutorial, since understanding layouts are the solution here, and just using BorderLayout isn't the way to solve it. You'll likely want to nest layouts, perhaps using BorderLayout for the overall GUI, and having a central JPanel use BoxLayout to allow you to stack components on top of each other inside of it. Then perhaps add this JPanel to the main JPanel that uses BorderLayout in the BorderLayout.CENTER position.
Just a hunch, but maybe you need to call repaint() in addition to revalidate()
Java Swing revalidate() vs repaint()

JPanel Obscures BufferedImage

I'm having trouble finding out why the following problem happens: In a program that uses "extends Frame" to create a window, I can use BufferedImage to draw to the graphics context of the Frame (not JFrame), and it looks just fine. However, the moment I declare a JPanel, all of the text drawn by BufferedImage becomes obscured (not completely, but semi-transparent and hard to read), even if I don't add the JPanel to the JFrame.
Here's a simplified version of the code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.Timer;
import java.awt.image.*;
import javax.swing.*;
public class MyProgram extends Frame {
static Frame f;
static Timer timer;
public static void main(String[] args) {
f = new Frame();
f.setSize(400, 200);
f.setResizable(false);
f.setVisible(true);
f.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
drawScreen();
}
});
drawScreen();
}
public static void drawScreen() {
BufferedImage off_i = new BufferedImage(f.getWidth(), f.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = off_i.createGraphics();
g.setColor(new Color(50, 50, 50));
g.drawString("Hit any key; why does this text change?", 15, f.getHeight() - 10);
Graphics off_g = f.getGraphics();
off_g.drawImage(off_i, 0, 0, null);
JPanel panel = new JPanel();
}
}
I could maybe understand seeing the problem arise if I had added the JPanel to the JFrame and didn't set any bounds to its visibility, but even creating the JPanel gives that issue, which seems weird to me.
Basically, what I'm trying to do here is take an existing program that I have that runs just fine without JPanel, and I want to add to it a JTextArea so that I can accept copy/paste text for modifying the displaying of the program.
My understanding of Java is kind of spotty, as I learned it mainly by hobby and not formally, but I'm always looking to learn more when I can. Thanks for the help!
Update: I discovered that this problem only happens when the draw function is called again, after the JPanel has been declared, though I still don't understand why it does that or how to get around it.
better would be put Image to the JLabel and how ot use Icon
please read Using Swing Components and how to LayoutManagers works
tons examples on java2s.com
Don't mix AWT components with Swing component. That is you should use a JFrame NOT a Frame.
Don't use getGraphics(). Custom Painting is done by overriding the paintComponent() method of a JPanel (or JComponent). You just use the Graphics object that is passed to the method. Then you add the panel to the frame.
As already mentioned using a JLabel is simpler because you don't have to do any custom painting. The tutorial also has a section on "How to Use Icons".
I tried to run your code. And although the effect that you are describing does not happen on my system I can recommend you something.
First try to create your panel before it is visualized. In this case java does not have to re-arrange the components that are already on screen.
Second, if you have to draw things on visible frame call validate() of the container when you are done. This makes java to re-arrange stuff.
Third, when you are using drawXXX() methods create your own class that extends Component, JComponent, Canvas and override its `paint(Graphics) method. In this case the system will call this method every time it needs (e.g. when window is resized) and your UI will be painted again.
BTW I have 2 questions:
why are you using drawText() instead
of Label or JLabel? Use them and
avoid such kind of problems.
Why do you extend your class from Frame and do not use this fact but create yet another instance of Frame?
As an answer to my original question:
It seems that initializing JPanel alongside awt draw() commands causes the text to be antialiased, which makes the text look harder to read, partially obscured, thinner, etc. Although I tried setRenderingHint() with VALUE_TEXT_ANTIALIAS_OFF, it did not solve the problem. But as other posters pointed out it's not best practice to mix the two components.
While this doesn't exactly solve my problem, it does answer the question of what is going on, that being text antialiasing as some result of JPanel (does that sound right?). Ideally I wouldn't want to rewrite all of the code just to add a single JTextArea into an already existing codebase. But perhaps it's good every now and then to revisit old code and revamp it where it may be faulty.
Thanks everyone for the comments, information, and resource links!

Why will BoxLayout not allow me to change the width of a JButton but let me change the height?

I'm trying to get the Layout of a JDialog of mine to fit a particular look that a program in which I'm porting to Java has, I've used several LayoutManagers before with great success yet for some reason I cannot seem to get this working at all. My goal is to have the Right (East) side of the JDialog contain a "Find Next" and "Cancel" button in a top-down order and then any extra space below so that the two buttons are always at the top of the JDialog, yet for some reason BoxLayout is continously ignoring any attempts at changing (this is where I'm lost) the width of a JButton. Code follows.
JButton findNext = new JButton("Find Next");
JButton cancel = new JButton("Cancel");
cancel.setPreferredSize(new Dimension((int)findNext.getPreferredSize().getWidth(),
(int)cancel.getPreferredSize().getHeight()));
JPanel example = new JPanel();
example.setLayout(new BoxLayout(example, BoxLayout.Y_AXIS));
example.add(findNext);
example.add(cancel);
example.add(Box.createGlue());
No matter what I try, cancel always retains it's normal size. I've tried setMinimumSize() and setMaximumSize() with the same parameters as setPreferredSize with no luck. I've even tried cancel.setPreferredSize(new Dimension(500, 500)); and the buttons height was the only thing adjusted, it STILL retained the default width it was given.
To clear up any questions, here is what it looks like (now that I've finished it) and you'll see that the "Find Next" and "Cancel" buttons are not the same size.
I know this is an old question but I don't really see a good explanation. So for the sake of searchers that stumble upon this I will add my two cents.
There are three methods associated with sizing components in Swing: setPreferredSize(), setMinimumSize(), and setMaximumSize(). However, the important point is that it is up to the particular layout manager being used as to whether or not it honors any of these methods.
For BoxLayout (the layout the original poster is using):
setMinimumSize() -- BoxLayout honors this
setMaximumSize() -- BoxLayout honors this
setPreferredSize() -- if X_AXIS is being used width is honored, if Y_AXIS is being used height is honored
The OP is using a Y_AXIS BoxLayout which is why only his height was being changed.
Update: I put together a page with this same information for all of the layout managers. Hopefully it can help some searchers out: http://thebadprogrammer.com/swing-layout-manager-sizing/
You may not want Box.createGlue(), which "grows as necessary to absorb any extra space in its container." Instead, use Box.createVerticalStrut() between the buttons, as shown below and in the ControlPanel of this simulation.
example.setLayout(new BoxLayout(example, BoxLayout.Y_AXIS));
example.add(findNext);
Box.createVerticalStrut(10);
example.add(cancel);
Addendum:
adding in setMaximumSize() made it work.
This is the expected behavior for components having identical maximum widths in a vertical BoxLayout, as described in Box Layout Features. The preferred width of the container becomes that of the (equally wide) children, and the X alignment becomes irrelevant.
example.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JButton findNext = new JButton("Find Next");
JButton cancel = new JButton("Cancel");
Dimension d = findNext.getMaximumSize();
cancel.setMaximumSize(new Dimension(d));
example.add(findNext);
example.add(cancel);
As mentioned in the comments on the question, you were able to fix it by switching to setMaximumSize(). However, as you noted, setPreferredSize() doesn't work. So, what's up with that?
With many things Swing, the properties used to determine the actual component size when using the BoxLayout are somewhat random (in my opinion). When determining how to render the components, Swing calls layoutComponent() on the layout manager, which is figures out where to position everything.
BoxLayout's implementation of layoutComponent() involves a call to a method that creates SizeRequirements objects for the width and height of each of the components you add to the JPanel, based on their getMinimum/Preferred/MaximumSize() methods.
Later, it calls SizeRequirements.calculateAlignedPositions() for determining the correct width values for each component, because your orientation is BoxLayout.Y_AXIS (The heights are calculated using a different method). Taking snippets from the source, the relevant implementation of this method is as follows:
for (int i = 0; i < children.length; i++) {
SizeRequirements req = children[i];
//...
int maxAscent = (int)(req.maximum * alignment);
int maxDescent = req.maximum - maxAscent;
//...
int descent = Math.min(totalDescent, maxDescent);
//...
spans[i] = (int)Math.min((long) ascent + (long)descent, Integer.MAX_VALUE);
}
Note that totalDescent is the available width, so descent is always set to maxDescent, which is based on SizeRequirements.maximum, which was taken from JButton.getMaximumSize(). The value of spans[i] is then used later in a call to JButton.setBounds() as the width. As you'll note, getPreferredSize() was never involved here, which is why setting it has no impact in this case.
Usually if want to ensure a size of the component in Swing you need to call setMinimumSize(), setMaximumSize(), and SetPrefferedSize() with the same value.
button.setMaximumSize(getMaximumSize());
If you put your buttons in a GridLayout panel they will be the same width.

Categories

Resources