I am implementing a Comment box facility in my application which user can resize using mouse. This comment box contains a scrollpane which instead contains a JEditorPane in which user can insert comment. I have added the editor pane inside a scroll pane for the following reason:
auto scolling of jeditorpane
When the user resizes the comment box, I am setting the desired size for JScrollPane and the JEditorPane. When the user is increasing the size of the comment box, the size of these components are increasing as desired but when the size of the comment box is decreased, the size of the JEditorPane does not decrease even after setting the size. This leads to the scrollbars inside the scrollpane.
I tried using setPreferrredSize, setSize, setMaximumSize for JEditorPane. Still the size of the editor pane is not reducing. I tried calling revalidate() or updateUI() after the setting of size but no use.
I am using Java 1.4.2.
Please provide me some insight....
I realise this is long since answered, but for future reference all you need to do is override the getScrollableTracksViewportWidth() to always return true, eg.
JEditorPane pane = new JEditorPane() {
public boolean getScrollableTracksViewportWidth() {
return true;
}
};
panel.add(new JScrollPane(pane));
Actually it is possible, luiscubal. Here is how,
To the JScrollPane add a ComponentListener for resize events
public static void main(String...args) {
//our test frame
JFrame frame = new JFrame("JEditorPane inside JScrollPane resizing");
frame.setLayout(new BorderLayout());
//our editing pane
final JEditorPane editor = new JEditorPane();
//our simple scroll pane
final JScrollPane scroller = new JScrollPane(editor);
//NOTE: this is the magic that is kind of a workaround
// you can also implement your own type of JScrollPane
// using the JScrollBar and a JViewport which is the
// preferred method of doing something like this the
// other option is to create a JEditorPane subclass that
// implements the Scrollable interface.
scroller.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
editor.setSize(new Dimension(
scroller.getWidth()-20,
scroller.getHeight()-20));
}
});
//just use up the entire frame area.
frame.add(scroller, BorderLayout.CENTER);
//quick and dirty close event handler
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(320, 240); //something not too big
frame.setLocationRelativeTo(null); //centers window on screen
frame.setVisible(true); // normally done in a SwingUtilities.invokeLater
}
Look luiscubal it is possible. Don't be so quick to announce things in Java as not possible. The swing api is quiet flexible and can do a lot of the work for you. However, if you use JComponents in ways they weren't made to be used you will end up with problems and have two options.
subclass subclass subclass basically create your own component.
find a work around, like the above solution.
Decreasing the size of a JEditorPane in a JScrollPane and then reducing it, is not possible.
You may want to use a JTextArea instead.
Related
I have been searching for a while now, but couldnt find a solution so I have decided to ask here.
I am using Java Swing for my gui implementation of calculator. I have custom made layout(which works correctly 100%). I have added all buttons and all buttons are positioned correctly, always. Last component I have inserted is "Inv" and it is checkbox which I cant find a way to center it inside its area. I have tried putting it in panel,in panel with borderlayout.center, setting the horizontal and vertical text alignment, but nothing works.
invert = new JCheckBox("Inv");
invert.setBackground(Color.decode("#8DA336"));
invert.addActionListener(new CommandListener(this,"invert"));
container.add(invert, new RCPosition(5, 7));
This RCPosition is nothing more than object which says in which row and column this component is (nothing wrong with that).
Checkbox is by default left-aligned. Try make it center-aligned:
invert = new JCheckBox("Inv");
invert.setHorizontalAlignment(SwingConstants.CENTER);
// styling and add to container
If it don't help, then you should publish your layout manager.
You could try putting it in a JPanel with BoxLayout, then add horizontal glue on the left and right.
final JFrame frame = new JFrame();
final JPanel jp = new JPanel();
jp.setLayout(new BoxLayout(jp, BoxLayout.X_AXIS));
jp.add(Box.createHorizontalGlue());
final JCheckBox jcb = new JCheckBox("inv");
jp.add(jcb);
jp.add(Box.createHorizontalGlue());
frame.getContentPane().add(jp);
frame.pack();
frame.setLocationRelativeTo(null);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame.setVisible(true);
}
});
This is just one way to do it, setHorizontalAlignment should work as well.
We're about to create an online based Space Invaders-game with implemented graphics. I've been reading about JFrames, JPanels and JLabels in order to create a window with a grid where the ships and monsters will be placed in.
So, here's the thing, I've been looking through the different layouts that exists, but nothing really seems to fit our purpose. I would like a simple JFrame with the possibility of placing JLabel-objects on a certain position (with setBounds(), setLocation() or something similar). This requires setLayout(null) which I've heard isn't a good solution? I was thinking of having objects in a fixed 30x30px size, and a fixed window size of 600x600px (giving me a grid of 20*20).
Anyhow, I've been trying to get it to work with setLayout(null), but without any results. If I apply a layout, say FlowLayout, the ship is visible, but stuck in either LEFT, CENTER or MIDDLE.
public class GUI extends JFrame {
JPanel p = new JPanel(null);
public GUI() {
try{
this.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("graphics/bg.png")))));
}catch(IOException e) {
System.out.println("Image does not exist");
}
this.setLayout(null);
this.setResizable(false);
this.setSize(600,600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public void placeShip1() {
ImageIcon ship2 = new ImageIcon("graphics/ship2.png");
JLabel imageLabel = new JLabel(ship2);
imageLabel.setBounds(200,200,30,30);
p.add(imageLabel);
p.setOpaque(false);
p.setSize(600, 600);
this.add(p);
this.setVisible(true);
}
}
I really can't see why it doesn't work. I mean, all I want is my JFrame with a background image and with an object on a certain position, but instead the object doesn't show at all.
The main reason for wanting to use setLayout(null) is because I was thinking of using a method translating our grid coordinates to the JFrame, simply mapping each coordinate to respective cell.
I am trying to use Java Swing to create a simple GUI in which I have a drawing pad and some buttons it all works fine until I add this code for the JTextField:
String text = "hello";
JTextArea textArea = new JTextArea(text);
textArea.setPreferredSize(new Dimension(500, 50));
textArea.setEditable(false);
Before adding this code the drawpad displays on the left of the screen followed by the buttons, when I add this only the drawpad is displayed unless I resize the frame in which case the buttons and text field reappear although the text field is hidden behind the drawpad slightly. Here is the full code:
public class testGUI extends Frame{
public static void main(String[] args) {
JFrame frame = new JFrame("Neural Networks");
frame.setSize(700, 300); //set the size of the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true); //make it visible
Container content = frame.getContentPane();
content.setLayout(new BorderLayout());
JPanel mainPanel = new JPanel();
final PadDraw drawPad = new PadDraw();
drawPad.setSize(100, 100);
content.add(drawPad);
JButton clearButton = new JButton("Clear");
clearButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
drawPad.clear();
}
});
JButton loadButton = new JButton("Load");
loadButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//Load something here
}
});
JButton testButton = new JButton("Test Draw Pad Image");
testButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//
}
});
JButton loadImage = new JButton("Test image from file");
loadImage.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//String filename = textField.getText();
}
});
String text = "hello";
JTextArea textArea = new JTextArea(text);
textArea.setPreferredSize(new Dimension(500, 50));
textArea.setEditable(false);
mainPanel.add(clearButton);
mainPanel.add(loadButton);
mainPanel.add(testButton);
mainPanel.add(loadImage);
mainPanel.add(textArea);
content.add(mainPanel);
}
}
You're adding the drawPad and the mainPanel to the content panel, which uses BorderLayout, without specifying any location. They thus end up both in the center position of the border layout, which is supposed to contain only one component.
See How to use BorderLayout in the Swing tutorial.
Also note that setting the preferred size is not something you should do. Instead, the preferred size is supposed to be automatically computed based on other sttings (the contained components, the number of rows and columns of a text area, etc.)
And a JTextArea should be enclosed into a JScrollPane to be good-looking and allow you to scroll.
JPanel mainPanel = new JPanel();
The default layout for a JPanel is a FlowLayout, so all the components flow on a single row. If there is not enough room on the row then the components wrap to the next row.
So when you add the JTextArea the flow is disturbed. The solution is to use a combination of layout managers to get your desired layout effect. Read the section from the Swing tutorial on Using Layout Managers for more information and examples.
JTextArea textArea = new JTextArea(text);
textArea.setPreferredSize(new Dimension(500, 50));
Also, you should NOT set the preferred size of the text area (or any Swing component for that matter). Instead you should do something like:
JTextArea textArea = new JTextArea(rows, columns);
and let the component determine its own preferred size. Also a text area is typically used with a JScrollPane and then you add the scroll pane to your panel:
JScrollPane scrollPane = new JScrollPane( textArea );
Edit:
Taking a second look at your code you have many more problems.
The point of using a layout manager is to have the layout manager set the size and location of the components. So your code should not have any logic related to the size/location of a component.
When you use the add(...) statement on a BorderLayout without a constraint, the component gets added to the CENTER. However only the last component added is managed by the BorderLayout. So only the "mainPanel" is given a size/location by the layout manager. That is why you need the setSize(...) statement on the drawPad to make the component visible. Although you now have the problem that two components are painted in the same space.
So to see the drawPad on the left you might want to use:
content.add(drawPad.BorderLayout.LINE_START);
However this still probably won't work because I'm guessing you are doing custom painting on the draw pad which means you will also need to override the getPreferredSize() method of the class so the layout manager can use the information to determine the size of the component. Read the section from the Swing tutorial on Custom Painting for more information and working examples.
Finally some other issues:.
The setVisible(...) statement should be invoked AFTER all the components have been added to the frame.
To follow Java standards, class names should start with an upper case character.
You should NOT be extending "Frame". There is no need to extend any class in your example.
Read the tutorial and download the demos for examples of better structured code.
I'm working on a class extending JDialog. I have a JPanel field named "panel" inside it, which is added to the contentPane (another JPanel), and I add the components that are intended to be displayed to "panel".
"Panel" always has the same size as the window itself. (It's practically a duplicate of contentPane.) But the window's size is different by every run, its size is counted in the constructor of the class based on the value of some specific fields that come from the program's business logic. (This size is static through one run, but when writing the code I don't know the exact numbers yet, only the method how to count it.)
This size could sometimes be very big, but I never want my window to be bigger than a specific size, e.g. (1300,800). When the window would be not larger than this size, I don't want the scrollbars to appear. When it would be larger than this on one dimension only, I only want the appropriate scrollbar to appear (vertical / horizontal). And when it's larger on both dimensions, then both scrollbars should appear.
I have read at least 50 tutorials and questions on this topic, here and on other similar forums. And I tried every idea that I found, in every different combination I could only think of. But none of them worked, and now I'm already very desperate.
It might be because neither my contentPane, nor "panel" uses a layout manager. They both use null. I read by another question that we have to set the preferred size of the component we want to be scrolled, but setPreferredSize leans on a layout manager. They there wrote that they don't really have an idea how to solve this issue, else than starting using a layout manager.
But if I start using one, it confuses the layout that I have designed, it ruins the x, y values, which I have set manually by each component. Layout is important in my exercise. It's not right if a layout manager confuses it, and I don't really like for this excercise how the different layout managers set the layout.
Could you give me any ideas on how I could make scrollbars work keeping using null layout manager?... :/
Here's my class Kimenet (Kimenet is the word for "output" in my mother tongue):
public class Kimenet extends JDialog {
private JPanel contentPane, panel;
private int window_width, window_height;
public static Kimenet showDialog(...) {...}
public Kimenet(...){
window_width = ...; //some counting here
window_height = ...; //some counting here
GUI();
}
private void GUI(){
setBounds(0, 0, window_width, window_height);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(null);
setContentPane(contentPane);
panel = new JPanel();
panel.setLayout(null);
panel.setBounds(0, 0, window_width, window_height);
contentPane.add(panel);
//here is where I try to add the scrollbars in every desperate way......
... components that I wanna add: panel.add(component);
}
Here's the part of the Main class from where I make an instance of Kimenet:
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Kimenet dialog = Kimenet.showDialog();
dialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
dialog.setModal(true);
dialog.setVisible(true);
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
}
}
});
I have tried adding the scrollbars from Main before making the dialog visible, and from Kimenet's GUI() method as well.
I have tried creating JScrollPane in many different combinations, but this mostly resulted that the scrollbars still didn't appear, but every component that I added to "panel" disappeared.
panel.setPreferredSize(new Dimension(1000, 600));
JScrollPane scrollpane = new JScrollPane(panel);
panel.setAutoscrolls(true);
scrollpane.setPreferredSize(new Dimension(800, 300));
this.add(scrollpane);
I've tried here this.add(scrollpane), contentPane.add(scrollpane), panel.add(scrollpane), scrollpane.add(contentPane) and many combinations.
I have tried creating JScrollBars separately in many different combinations too, but this mostly resulted that the scrollbars simply didn't appear (I have tried much more combinations than what I copy here, e.g. vertical and horizontal scrollbar policy.)
vertikális = new JScrollBar(JScrollBar.VERTICAL, 0, 10, 0, 100);
vertikális.setPreferredSize(new Dimension(700, 600));
contentPane.add(vertikális);
This didn't work in no way either.
I just can't get this right. I have a slider to increase my JPanel's size (used as a canvas to draw on).
Whenever the JPanel receives the event, I resize it with setBounds() and I can see it resizing for a split second, but a next Paint or something switches it back to the original size given by the slider's preferred size property.
public class ShapesMainFrame extends JFrame {
private PaintCanvas paintCanvas;
public ShapesMainFrame() {
[...]
JScrollPane scrollPane = new JScrollPane(paintCanvas);
scrollPane.setPreferredSize(new Dimension(1,600));
add(scrollPane, BorderLayout.CENTER);
pack();
}
}
public class PaintCanvas extends JPanel {
[...]
public void setScale(int value) {
setSize(1000,1000);
}
}
So when I try to change the size of the JPanel to a big value it should resize and the scrollbars should appear right? Well it stays the same 600px tall how I set it at the start.
Never use setSize() or setBounds when using a layout manager. Its the "preferred size" that is important. Normally the preferred size of a component is determined automatically by the layout manager. But if you are doing custom painting on the panel you may need to determine the preferred size manually.
The scrollbars will appear when the preferred size of the panel is greater than the size of the scroll pane. Override the getPreferredSize() method (preferred solution) or use the setPreferredSize() method of the custom panel.
All you need to do is call revalidate() on the content within the JScollPane after updating it's size. Also, use the setPreferredSize() when using a layout manager.
public void setScale(int value) {
setPreferredSize(new Dimension(1000, 1000);
revalidate();
}
That will force the JScrollPane to update it's scrollbars.
Also, you could call
paintCanvas.revalidate()
If you wanted to update the JScrollPane from outside of your paintCanvas class