I am writing GUI program in Java.
I have a JPanel called jpanel1 that I inserted a JSplitpane (jSplitPane1) on it. I set right and left components of jSplitPane1; jpanel2 & jpanel3. I set a background image on downward panel (jpanel1) and I want to JSplitPane and it's right and left components be transparent such that I can see the background image on them. Is this possible in Java? If this is possible can I use that method to transparent JTree as JSplitpane?
You simply need to call: setOpaque(boolean).
It depends on the L&F. AquaL&F on MacOS will respect setOpaque(false) but e.g. Nimbus does not seem to care about it. To force a transparent divider you need to override it in the UI definition of the JSplitPane
jSplitPane.setUI(new BasicSplitPaneUI(){
#Override
public BasicSplitPaneDivider createDefaultDivider() {
return new BasicSplitPaneDivider(this){
#Override
public void paint(Graphics g) {
}
};
}
});
A potential disadvantage is that this approach overrides the L&F for this component and thus might take away other L&F theming elements.
Related
This is probably a very basic question, but I could't find anything about it online.
I'm working in Java swing and have a JPanel with a null Layout Manager (ie using absolute positioning). The JPanel is filling a space in the JFrame so that its size will change when the JFrame is resized. Within this JPanel, I have a number of other components that I have placed using Component.setBounds(). I would like one of these components to be set relative to the bottom of the JPanel, so that when the containing JPanel resizes, the smaller JComponent stays stuck to the bottom of the container.
I have tried to do this by overriding the getLocation() or getBounds() methods to reference the container height, but neither of these seemed to work the way overriding getPreferredSize() would, even after calling revalidate() and repaint(). Unfortunately, using another layout manager like BorderLayout is not an option here.
Is there a way to do something like this? Am I missing something obvious? If not, is there a way to listen for changes in the container's height and re-call .setBounds()?
Try listening to the resize event of the panel:
panel.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent arg0) {
component.setBounds(...);
}
});
You can reference panel.getBounds from withing this method and set your components bounds accordingly.
To do this you can add a component listener to your JFrame.
addComponentListener(new ComponentAdapter(){
public void componentResized(ComponentEvent e){
//Do stuff here
}
});
Inside the component listener you can change the sizes and locations of anything you would like to. To stick them to the bottom simply get the size of the JFrame and subtract a specific amount and set that as the y location for what you want stuck to the bottom.
I am having a hard time to properly set the way my swing components behave on resize.
I have two problems with that interface:
A: The toggle button at the beginning of each row is here to collapse/expand the text. All the elements are contained in a JLayeredPane. On the button click, I edit the pane's height to expand or collapse the content (either 31 or 310). Expand works fine an pushes the elements below. On the other hand, collapse does hide the text but leaves all the elements in position. Here is my code:
private void expandText(java.awt.event.ActionEvent evt) {
JToggleButton button = (JToggleButton) evt.getSource();
Container parent = button.getParent();
Dimension size = parent.getSize();
String icon;
if (button.isSelected()) {
size.height = 310;
icon = "/org/cytoscape/ocsana/resources/images/minus.png";
} else {
size.height = 31;
icon = "/org/cytoscape/ocsana/resources/images/plus.png";
}
parent.setSize(size);
try {
button.setIcon(new ImageIcon(ImageIO.read(getClass().getResource(icon)).getScaledInstance(-1, 15, Image.SCALE_SMOOTH)));
} catch (IOException ex) {
}
backgroundPane.revalidate();
backgroundPane.repaint();
}
B: The screenshot above is the minimum size of the window. When I resize the window horizontally, the inner pane only resize to the value of min + (frame.width - min) / 2 meaning my right scrollbar does not stick to the right side of the frame.
See below a demonstration of the both problems:
Well, you could add a listener to the frame so have an action on event when the frame is being resized. And then pack() the frame.
public final class TestFrame extends JFrame {
(...)
this.getRootPane().addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
this.pack();
this.revalidate();
}
});
}
It you are using the paint graphic method, you should as well repaint() your frame.
In that method you can also manyally set the preferred size of the window by computing it based on e.getWidth()
How does your expand/collapse code work? Do you just make component visible/invisible, or do you add remove components from the panel?
On the other hand, collapse does hide the text but leaves all the elements in position.
If you add/remove components then the basic code is:
panel.remove(...);
panel.add(...);
panel.revalidate();
panel.repaint();
meaning my right scrollbar does not stick to the right side of the frame.
It depends on the layout manager you are using. I would guess the easiest would be to use a GrigBagLayout. It allows you to "fill" the space available. Read the section from the Swing tutorial on How to Use GridBagLayout for more information and examples.
All the elements are contained in a JLayeredPane.
Not sure why you are using a layered pane. By default a layered pane doesn't use a layout manager.
According to camickr answer and comments, see how I solved it:
Point A is due to my free layout used in NetBeans. I did not succeed to fix my code so I changed the structure of my elements. It is probably not optimal and does not use all the swing concepts right, but it works the way I want.
I have a JLayeredPane in the background that uses a GridBagLayout. This background pane contains one column of JPanel of height 30 and 260, one for the summary line, the other one for the details.
The expand/collapse function controlled by the JToggleButton works by hiding the below panel belowPanel.setVisibility(false). No need for repack or anything, just that. Here is how the code looks like without changing the button's icon:
private void inverseVisibility(JToggleButton expand, JPanel target) {
if (expand.isSelected()) {
target.setVisible(true);
} else {
target.setVisible(false);
}
}
As I only wanted the elements to resize horizontally, all my panels have Horizontal as Fill value and Northwest as Anchor. I've set the weightX = 1; weightY = 0. Finally I added a panel in the bottom with a Southwest anchor and fill both along with both weights to 1 (not sure it changes anything but this way I am certain that it will fill all the blank space at the bottom it the window is resized at a bigger size than its content).
Point B has been solved by taking my background panel, that fit in my Frame, and putting it into a JScrollPane. The error I had was due to the Netbeans editor that did not properly stick the scroll pane to the side of the frame, due to incoherences in the sizes defined in both the frame and the scroll pane. My advise to you if you are using this tool is to set the fewest values as possible as a lot of values are heavily interconnected by the gui designer.
Get the full code (95,864 bytes)
So I'm making this program with a GUI and I haven't worked with Swing/SWT too much but a little bit to know what's going on.
Anyway, I add an actionlistener for a button so it'll add an image to the contentPane when I click on the button but it doesn't work unless I have it as a JComponent (as seen below) and add my other things (button, JLabel, etc) to it afterwards...AND set this JComponent to the content view (which doesn't make sense).... I've also tried making it extend JPanel and just clearing out original contents and re-adding them to the new JPanel. The thing is, when I do this it recreates the text for my JLabel in a weird way, and I just know there's gotta be a simpler, more efficient, way.
class ShowImage extends JComponent{
public ShowImage(){
super();
monkey = Toolkit.getDefaultToolkit().getImage(("D:/monkey.png"));
}
public void paintComponent(Graphics g){
g.drawImage(monkey, 20, 100, null);
repaint();
}
}
Do not invoke repaint inside paintComponent
Invoke super.paintComponent and then draw the image
Also, depending on the layout manager, this component will have a preferred size of (0, 0), and therefore will not be visible.
For more information, see 2D Graphics.
Edit -
Note that dynamically adding a component will force you to revalidate the container and issue a repaint request so the layout manager will layout its components again and remove any visual artifacts. Also, for more information regarding images, see Working with Images.
Anyway, the simplest approach would probably be to set the image as the icon of a JLabel instance and add that to the container. There's really no need to reinvent the wheel here.
g.drawImage(monkey, 20, 100, this);
..would most likely have fixed the problem in the original code. It was a combined problem of:
Loading the image in an asynchronous way. (Toolkit.getImage() as opposed to ImageIO.read().)
Painting it to a 'blinkered' ImageObserver. The JComponent implements ImageObserver. As soon as the image is totally loaded (as well as a few points before that), the observer will be informed, triggering a repaint().
I am using intellij with swing.
My application runs on different computers with different monitors.
I want to display my form in different sizes.
I have a JPanel (not the main . inner jpanel ) set to (-1,670) in the intellij gui editor.
And I try to change it with this code :
MyFormUI myform = new MyFormUI();
if (thisIsTheCase){
myform.setLongView()
}
and in MyFormUI ->
public void setLongView(){
myPanel.setPrefferedSize(new Dimension(-1, 1000))
myPanel.repaint() ;
revalidate();
// I tried also repaint and revalidate on a higher jpanel in the hierarchy
}
When I change it in the gui editor - it does change, but not through code.
any suggestions?
myPanel.setPrefferedSize(new Dimension(-1, 1000))
myPanel.repaint();
revalidate();
Not sure what the -1 does.
The code should be:
myPanel.revalidate();
myPanel.repaint();
The revalidate() actually redoes the layout of the component and the repaint just paints it. In your code you are repainting before redoing the layout.
Preferred size is, as you may guess, only preferred. If the underlying layout manager does not want to use this setting, it is free to discard it. IntelliJ IDEA is using its own layout manager, so you need to check if the panels Horizontal and Vertical size policies allow resizing.
It will be easier to diagnose the problem if you describe your layout in more details.
Is it possible to draw on a JFrame without adding a JPanel to it?
i override paintComponents() but it didn't show anything.
#Override
public void paintComponents(Graphics g) {
super.paintComponents(g);
g.drawString("for test", 10, 10);
}
Just in case anybody still insists of painting on the top-level Window directly (which is not recommended), here's how (because the code snippet linked to in the other answer is simply wrong)
JFrame frame = new JFrame("funny ...") {
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawString("for test", 150, 150);
}
};
frame.getRootPane().setOpaque(false);
((JComponent) frame.getContentPane()).setOpaque(false);
Obviously, to make it shine-through all the way up, everything above (in Z-order) has to be not-opaque.
Cheers
Jeanette
Yes, it is. You'll want to work with the one of the panes in the JFrame such as the content pane or the glass pane, which you can access via getContentPane, etc.
For example the content pane is a Container, with a variety of add methods. To that you can add any Component - doesn't have to be a JPanel specifically. More at Using Top Level Containers.
Usually, though, drawing is done via overriding paint (for AWT) or paintComponent (for Swing). This means you need some sort of Component or JComponent that you put in your frame. More at the 2D Graphics tutorial. Why do you not want to change that?
You can also override JFrame and its content pane and have a content pane with an override paintComponent method.
I question, however, the necessity and wisdom of directly drawing on a JFrame.
It seems to be possible. Check this previous SO post to see how it can be done.
JFrames have a GlassPane on top of them, which can be used for graphics. Here you have a simple example that shows how to use it.