AWT TextArea inside JTabbedPane visual bug - java

JTabbedPane main_tabbedPane = new JTabbedPane( JTabbedPane.TOP );
main_tabbedPane.setBorder( new EmptyBorder( 0, 0, 0, 0 ) );
main_tabbedPane.setBounds( 10, 76, 665, 473 );
main_tabbedPane.setVisible(false);
main_content.add( main_tabbedPane ); // main_content is a jpanel
I then call a class constructor which extends JPanel
alphaStarter_tab = new AlphaStarterPnl();
which among other things has a TextArea (from Java AWT not JTextArea)
public class AlphaStarterPnl extends JPanel {
private TextArea outputTxtA;
public AlphaStarterPnl(){
outputTxtA = new TextArea("",4,50,TextArea.SCROLLBARS_VERTICAL_ONLY);
outputTxtA.setFont(new Font("Tahoma", Font.PLAIN, 13));
outputTxtA.setEditable(false);
outputTxtA.setBackground(new Color(179,190,201));
outputTxtA.setForeground(new Color(34,64,132));
outputTxtA.setBounds(15, 133, 630, 300);
add(outputTxtA);
}
}
I then add this panel (which has alot more to it than the pasted code, but that doesn't matter here) to the tabbed pane
main_tabbedPane.addTab( "Copy Files", null, alphaStarter_tab, null );
When I do this, despite main_tabbedPane having been set to setvisible false, the TextArea pops up and not only that but it also appears in three places. (Perhaps appearing once at the 0,0 coordinates, then at the set x,0 coordinates then at the set x,y coordinates. When I continue on in the program and this "flash of ugly content" goes away when a second tab is added.
Any thoughts?

The problem here can be that you are mixing lightweight components (i.e. Swing components like JTabbedPane, those with 'J' prefix) and heavyweight components (i.e. AWT components such as TextArea). Using these two types of components together can cause rendering issues.

Related

When hovering over element, a copy of the parent JFrame appears inside it [duplicate]

I have a dark-gray JPanel with a JLabel on it. I set new Color(0, 0, 0, .5f) (tranparent) as the background of the JLabel and I change the text several times using a button. The problem is, everytime the text is changed, the previous text still remains behind the new text. I change the text from "123456789" to "1234567", "12345" and "123". Here is the screenshot:
How do I get rid of this "shadow"?
I have a dark-gray JPanel with a JLabel on it. I set new Color(0, 0, 0, .5f) (tranparent)
Swing does not support transparent backgrounds.
Swing expects a component to be either:
opaque - which implies the component will repaint the entire background with an opaque color first before doing custom painting, or
fully transparent - in which case Swing will first paint the background of the first opaque parent component before doing custom painting.
The setOpaque(...) method is used to control the opaque property of a component.
In either case this makes sure any painting artifacts are removed and custom painting can be done properly.
If you want to use tranparency, then you need to do custom painting yourself to make sure the background is cleared.
The custom painting for the panel would be:
JPanel panel = new JPanel()
{
protected void paintComponent(Graphics g)
{
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
panel.setOpaque(false); // background of parent will be painted first
Similar code would be required for every component that uses transparency.
Or, you can check out Background With Transparency for custom class that can be used on any component that will do the above work for you.
This related example also makes the JPanel translucent.
try this, maybe it will solve your problem:
In actionPeroformed..
public void actionPerformed(ActionEvent e) {
final JLabel tmpLabel = new JLabel(value[++i]); //change text
label.setFont(new Font("Times New Roman", 1, 36));
label.setForeground(new Color(255, 255, 255));
label.setBackground(new Color(0, 0, 0, .5f));
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setOpaque(true);
label.setBounds(10, 10, 270, 70);
label = tmpLabel; //replace the entire label with a new label
}

JPanel inside JFrame doesn't show content sometimes. Why?

I managed to fix it but I don't understand why the same code results in different results. Some classmates have had the same problem.
The issue is that it I use miVentana.setVisible(true); before chicha(); the elements inside the JPanel will show when executing but if I run it again sometimes they won't ve visible until I resize the window, a few times not even the JPanel background color was visible. Just clicking the "Run" bottom on the IDE without changing anything else.
I just tried it 10 consecutive times and the elements were only visible on the 4th attempt.
Could this come from some memory garbage remaining from previous executions of the code?
I'm using Eclipse Version: Photon Release (4.8.0).
This is the code with the weird behaviour:
public class Ej10 extends JFrame {
public Ej10() {
setLayout(null);
}
static Ej10 miVentana = new Ej10();
public static void main(String[] args) {
miVentana.setTitle("Ejercicio10");
miVentana.setBounds(20, 20, 500, 600);
miVentana.setLocationRelativeTo(null);
miVentana.setVisible(true);
chicha();
//miVentana.setVisible(true);
}
static void chicha() {
JPanel miPanel = new JPanel();
miPanel.setLayout(new BoxLayout(miPanel, BoxLayout.PAGE_AXIS));
miPanel.setBounds(20, 20, 350, 450);
miPanel.setBackground(Color.CYAN);
JLabel lUsuario = new JLabel("Usuario:");
lUsuario.setVisible(true);
JTextField campoUsuario = new JTextField();
JLabel lPwd = new JLabel("ContraseƱa:");
JPasswordField campoPwd = new JPasswordField();
JButton bAcceso = new JButton("Acceder");
miPanel.add(lUsuario);
miPanel.add(campoUsuario);
miPanel.add(lPwd);
miPanel.add(campoPwd);
miPanel.add(bAcceso);
miPanel.setVisible(true);
miVentana.add(miPanel);
}
}
Components need to be added to the frame BEFORE the frame is made visible.
One of the functions of the setVisible() method is to invoke the layout manager. Otherwise components have a size() of (0, 0) so there is nothing to paint.
Also, all GUI components should be created on the Event Dispatch Thread (EDT), otherwise you can have random results. Read the section from the Swing tutorial on Concurrency for more information.
Take a look at the FrameDemo from How to Make Frames for the most basic example of how your code should be structured to avoid problems. It shows how to create components on the EDT and how to make the frame visible.
they won't ve visible until I resize the window,
Resizing the frame will also cause the layout manager to be invoked.
miPanel.setBounds(20, 20, 350, 450);
That statement will do nothing because the layout manager of the frame will determine the size and location of the panel based on the rules of the layout manager. The default layout manager for a frame is a BorderLayout, so basically the panel will get all the space available to the frame.
The tutorial also has a section on Layout Managers that you should read.

JLabel text Y paint coordinate

The default JLabel draws its text at the middle of its bounds. For example, if height of the label is 20, font height is 14, the Y coordinate would be (20 - 14)/2 = 3. Like this:
What should I do if want to align the text to the TOP of the JLabel bounds? Like this:
UPD:
public class LabelTest extends JFrame {
public LabelTest() {
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(500, 500);
setLocationRelativeTo(null);
JPanel contentPanel = new JPanel();
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.X_AXIS));
contentPanel.add(Box.createHorizontalStrut(10));
final JLabel label1 = new JLabel("JLabel");
label1.setVerticalAlignment(SwingConstants.TOP); // by the answer of Kevin Workman, doesn't help
label1.setBorder(BorderFactory.createLineBorder(Color.RED));
label1.setFont(new Font("Arial", Font.PLAIN, 14));
contentPanel.add(label1);
setContentPane(contentPanel);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new LabelTest();
}
});
}
}
You should be packing the frame. If you so this, there should be no unused space in the label. If you want empty space, use an empty border
label.setBorder(new EmptyBorder(0, 0, 5, 0));
top, left, bottom, right
Also, don't set sizes, Use Layout Mangers and let them do the sizing for you. Setting sizes will give you. Setting sizes will give you a rigid look that may look and perform differently on different platforms. Layout Managers will allow your GUI to be more fluid and adaptable to different environments.
See Laying out Components Within a Container for more information on working with layouts
Also see Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
As always, the API is your best friend: http://docs.oracle.com/javase/7/docs/api/javax/swing/JLabel.html#setVerticalAlignment(int)
Edit- Based on your updated SSCCE, the problem is that your BoxLayout is shrinking the JLabel as small as it will go, so the vertical text position doesn't really matter. Try using a BorderLayout to check that.
The problem is that the insets of the JLabel are adding a small space to the top and bottom of the JLabel, so your text looks centered even though it's at the top. Here's a fix for the insets problem: How to change gap in swing label

Java Swing and Component Positioning

I am creating a base class for the JFrames of my application. I would like to inject a JXSearchField in the top right and corner of all frames that inherit from this class. I have a web background and know CSS fairly well. The effect I am going for is a float:right; or Fixed position, where other elements are not effected by the height of this component.
An example of what I am talking about would be a JFrame with a JTabbedPane aligned at the top. My tab pane only has three tabs but my frame is 800px wide. This gives me plenty of space for my top right aligned search box but my tabbedpane is reserving that space for additional tabs. I want to float in or fix position my searchbox to overlay that space.
if I understand correctly, you want to paint the TextField over the JTabbedPane beside the Tabs?
There is no easy way in swing doing this. You can use a glassPane-Component which draw the TextField on top right. And set it to the Frame.
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
JFrame frame = new JFrame();
frame.setBounds( 50, 50, 800, 600 );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
JPanel glasspane = new JPanel(new FlowLayout(FlowLayout.RIGHT));
frame.setGlassPane( glasspane );
glasspane.setOpaque( false );
JTextField textField = new JTextField("Search");
glasspane.add(textField);
glasspane.setVisible( true );
JTabbedPane tabs = new JTabbedPane();
tabs.setBorder( BorderFactory.createEmptyBorder( 10, 5, 5, 5 ) );
tabs.addTab( "Lorem", null );
tabs.addTab( "Ipsum", null );
tabs.addTab( "Dolor", null );
frame.setContentPane( tabs );
frame.setVisible( true );
A Good Layout that a lot of people use for organizing SWING components is the GridBagLayout
GridBagLayout

Swing: Alignment Problem

I have a question about laying out some swing components.
Say, I have a JPanel which contains a JLabel and a JTextField. I want JLabel to be drawn on the left-most side of JPanel, and JTextField to be drawn on the right-most side of JPanel. I tried using BoxLayout and Horizontal Glues, but I couldn't make it work. Can somebody explain how this should be done? And by the way, I also should be able to set the JTextField's size, which will grow from right to left.
EDIT: Here is my class, it's pretty simple.
public class TextField extends JPanel {
private JLabel label;
private JTextField textField;
public TextField(String labelText){
this.label = new JLabel(labelText);
this.textField = new JTextField("");
Box horizontalBox = Box.createHorizontalBox();
horizontalBox.add(label);
horizontalBox.add(Box.createHorizontalGlue());
horizontalBox.add(textField);
add(horizontalBox);
}
}
One of the best ways to debug swing UIs is to add visible borders to your components to get a better idea of what is going on.
Try adding this after you create the horizontalBox:
horizontalBox.setBorder(BorderFactory.createLineBorder(Color.black));
Most likely what you will find is that your TextField is shrunk to the absolute minimum size required to display whatever text you pass to the constructor and the minimum size of the JTextField (which is basically just one visible character space).
Now try adding this to the constructor:
horizontalBox.setPreferredSize(new Dimension(400, 40));
Then try replacing the glue with a strut:
horizontalBox.add(Box.createHorizontalStrut(30));
That said, I think the biggest issue is that you are using a JPanel and then adding a box component to it, which makes resizing of the component problematic.
Try this and see if it works for you:
public TextField(String labelText){
this.label = new JLabel(labelText);
this.textField = new JTextField("");
this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
this.setBorder(BorderFactory.createLineBorder(Color.black)); // debug
this.add(label);
this.add(Box.createHorizontalStrut(30));
this.add(textField);
}
[p.s.]
You really want to reconsider the name of that JPanel extension. Perhaps TextFieldDisplay or TextFieldPanel would be more appropriate.
You could also use border layout and add the label using the BorderLayout.WEST option and the TextField using the BorderLayout.EAST option.
I tried using BoxLayout and
Horizontal Glues, but I couldn't make
it work. Can somebody explain how this
should be done?
There is no trick to this. Read the Swing tutorial on How to Use Box Layout for a working example.
If it still doesn't work then you need to post your SSCCE because we can't guess what you might be doing wrong.
To use BoxLayout:
public TextField(String labelText){
this.label = new JLabel(labelText);
this.textField = new JTextField("");
this.setLayout( new BoxLayout( this, BoxLayout.X_AXIS ) );
this.add( label );
this.add( Box.createHorizontalGlue() );
this.add( textField );
}
I like to use GridBagLayout for panels that have either complex layouts or components that should "fill" part of the panel.
JPanel panel = new JPanel();
JLabel label = new JLabel( "Enter your text:" );
JTextField textField = new JTextField();
panel.setLayout( new GridBagLayout() );
panel.add( label,
new GridBagConstraints( 0, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.EAST, GridBagConstraints.NONE,
new Insets( 0, 0, 0, 0 ), 0, 0 ) );
panel.add( textField,
new GridBagConstraints( 1, 0, 1, 1, 1.0, 0.0,
GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
new Insets( 0, 0, 0, 0 ), 0, 0 ) );
You can find a good explanation of how you use GridBagLayout here.
The problem with the code that you posted isn't so much the BoxLayout, it's the layout that contains it. By default, JPanel uses FlowLayout. When you add a component to a FlowLayout it does not expand to fill all of the available space.
So, instead of adding a Box to the panel, either make the class extend Box or set the panel layout to BoxLayout and add the components directly.
Set your JPanel to use BorderLayout. This, in combination with Box will give you almost any layout you need.

Categories

Resources