Layout trouble within JTextPane - java

I am sorry for the lack of a better title, but I have no idea how to specify the error further, since I don't understand its nature. Maybe someone can edit it, when the problem is understood.
I am writing an application in which the user can add icons into a text field. I obviously picked a JTextPane to display the text and the icons. After playing around with the insertComponent() function of the class I ran into some weird layout problems, so I decided to lookup the tutorial at oracle.com. After looking at the source code of the example, I decided to do the same and also use styles to add components to the underlying StyledDocument. It was when I started the first test run, when I discovered, that the layout problems stayed the same.
So, what is actually happening?
What I intended the text pane to show is "abcOdefO", but as you can tell by the screenshot, the two icons (circles) have some space to the right of them. I want the icon to be treated as a slightly larger character, so it should only occupy as much space as it needs, not (availableSpace / numberOfIcons), which seems to be what it actually occupies.
When typing another character at the caret position:
This is even weirder. If the icons have MouseListeners, all 4 visible circles trigger the event. If I drag the frame to another window or minimize and restore it, the weird parts vanish and the frame looks like the first image (except for the additional character). So I guess, this part of my problem is fixed with a call to repaint() at the correct location - but where?
This is the code that produces the images seen above:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
public class TextPaneTestPanel extends JPanel {
private class myIcon extends JPanel {
private final int side;
private final int padding = 1;
public myIcon(int size) {
this.side = size - 2 * padding;
this.setSize(size, size);
this.setPreferredSize(getSize());
this.setMinimumSize(getSize());
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(2));
g2d.drawOval(padding, padding, side, side);
}
}
private final JTextPane textPane;
public TextPaneTestPanel() {
textPane = new JTextPane();
StyledDocument doc = textPane.getStyledDocument();
Style def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
StyleConstants.setFontFamily(def, "Monospaced");
Style regular = doc.addStyle("regular", def);
try {
doc.insertString(0, "abc", regular);
Style s1 = doc.addStyle("icon1", regular);
StyleConstants.setComponent(s1, new myIcon(20));
doc.insertString(3, " ", s1);
doc.insertString(4, "def", regular);
Style s2 = doc.addStyle("icon2", regular);
StyleConstants.setComponent(s2, new myIcon(20));
doc.insertString(7, " ", s2);
} catch (BadLocationException e1) {
e1.printStackTrace();
}
this.setLayout(new GridBagLayout());
this.add(textPane, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(4, 4, 4, 4), 0, 0));
}
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
TextPaneTestPanel panel = new TextPaneTestPanel();
frame.getContentPane().add(panel);
frame.setSize(300, 100);
frame.setVisible(true);
}
}
To sum up my questions:
What causes the space to appear after an icon?
Where do I add the repaint() or revalidate() to fix the problem seen in image #2?
P.S.: I know, that my "icon" does not implement Icon, but it shouldn't be necessary, since JTextPanes can handle all sorts of Components.

1.What causes the space to appear after an icon?
Well, you have the following code:
this.setMinimumSize(getSize());
What about the maximum size?
How to fix the problem seen in image #2?
Custom painting is done by overriding the paintComponent() method, not the paint() method and don't forget to invoke super.paintComponent.
An Icon would be more appropriate here since all you are doing is custom painting. Or even a JComponent, but not a JPanel which is a Container used for holding other components. Plus is you use an Icon you don't have the size problems that you have with a panel, or JComponent since that method is specifically implemented as part of the interface.

Related

Show multiple JPane images on a single JFrame

First off, I am new to JFrame and all the associated classes so I am still learning how to do this.
My current goal is to draw multiple images on a single JFrame. So far, I can get test2.png to draw, but not test1.png. Any suggestions or help understanding JFrame is appreciated. This is my main class:
package com.osj.oneshotjava;
import java.awt.Dimension;
import javax.swing.JFrame;
/**
*
* #author BCG04
*/
public class actorTest {
public static void main(String []args){
JFrame jFrame = new JFrame("OSJ actor test");
jFrame.setPreferredSize(new Dimension(640, 480)); // sets window size
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Actor2 Background = new Actor2(jFrame, "test1.png");
Actor2 testActor = new Actor2(jFrame, "test2.png");
jFrame.pack(); // automatically adjusts window size (also sets window size based on the maximum and minimum sizes)
jFrame.setVisible(true);
}
}
And this is Actor2:
package com.osj.oneshotjava;
import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
*
* #author BCG04
*/
public class Actor2 { //Purpose: make it easer to add multiple images to a single JFrame using only a single call to Actor2's constuctor rather than repeating the same section of code for each image.
private BufferedImage image = null;
private JLabel jLabel = null;
public Actor2(JFrame jFrame, String filename){
try
{ // try to load a image 'filename' into 'image'
image = ImageIO.read(new File(filename));
}
catch (Exception e)
{
e.printStackTrace(); // if loading fails, print the error
System.exit(1); // then exit with an error code 1 'unsuccessful exit'
}
ImageIcon imageIcon = new ImageIcon(image); // create a new ImageIcon that contains 'image'
JPanel jPanel = new JPanel();
jLabel = new JLabel();
jLabel.setIcon(imageIcon); // set JLabel 'jLabel' to contain 'imageIcon'
jPanel.add(jLabel);
jFrame.getContentPane().add(jPanel, BorderLayout.CENTER); // makes window visible?
}
public JLabel getJLabel(){
return jLabel;
}
}
Edit:
-removed Thread.sleep(1000); and setLocation(90, 90); since they were not relevant to the question or the problem and I originally had them in to test whether I could move images.
-removed jLabel.setBounds as it did not seem to do anything.
+added a comment clarifying Actor2's goal.
I'd like to clarify my end goal, I would like to create a simple 2d game that uses Java.
Here is a complete, self contained example that is close to what you're after. It is to demonstrate the use of a layout manager.
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
public class DuelingJLabels{
public static void startGui(){
JFrame frame = new JFrame();
JPanel scene = new JPanel();
Actor red = new Actor(Color.RED);
Actor blue = new Actor(Color.BLUE);
//scene.setLayout( null );
scene.add(red.image);
scene.add(blue.image);
//scene.setPreferredSize( new Dimension(512, 512) );
frame.add(scene, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
static class Actor{
int x, y;
JLabel image;
public Actor(Color c){
BufferedImage a = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics g = a.getGraphics();
g.setColor(c);
g.fillOval(0, 0, 64, 64);
image = new JLabel();
image.setIcon(new ImageIcon(a));
image.setLocation( x, y );
image.setSize( 64, 64);
image.addMouseListener( new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent evt){
x = x+64;
if(x>=448){
x = 0;
y += 64;
}
image.setLocation(x, y);
}
});
}
}
public static void main(String[] args){
EventQueue.invokeLater( DuelingJLabels::startGui );
}
}
Take note of the line scene.setLayout(null); if you run the example with that line commented out, then you will see two circles side by side. That is because we are letting swing handle the layout. scene is a JPanel with a FlowLayout by default.
Now when you click the circles, nothing happens* because we tell the new position but the layout manager resets the position.
*Actually they move sometimes, but if you trigger a re-validation then they get moved by the layout manager.
So now remove the comment on scene.setLayout(null); and notice the difference.
The frame is tiny, and we have to manually resize it to see our scene.
There is only one circle.
If you click on the circle, it moves.
That's because we have told swing to not use a layout manager for the JPanel scene. That means it will not reposition the components in the scene for us, and it will not adjust the sizes for us either.
The other line that is commented setPreferredSize makes scene tell the parent component a size it would like to be at. If you uncomment that line then the JFrame will not start out incredibly small. You should only use that with custom components, otherwise you can end up conflicting with the layout manager.
Another tool, which I have found usefull is the JLayeredPane because it gives you some depth. I also think the example is good.
Finally, another technique for putting custom graphics arbitrarily is to #Override paintComponent. That way you can draw whatever, where-ever on your component.

Background is not painted

I want to create a simple game menue for the game pong. In the background there is a ball that bounces of the edges just to look nice. Now I want to add Buttons to this menue screen. But then the Background isn't painted anymore. So i want to draw a live Background but the buttons should still stay in the front. This live Background is implemented with a loop. In the following are the GUI class and the DrawStartMenueClass.
I heard about Layers but everybody uses them with some kind of tool in NetBeans and I got eclipse so I don't have that opportunity. I guess you can put the buttons and the background in different containers but then again I am not sure how that would. Every help is welcome.
public class GUI {
public GUI() {
//Frame erzeugen
Var.frame = new JFrame("Pong");
Var.frame.setSize(Var.dimension);
Var.frame.setVisible(true);
Var.frame.setResizable(true);
Var.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Var.frame.setLocationRelativeTo(null);
//Komponenten erzeugen
Var.start = new JButton("Start");
Var.optionen = new JButton("Optionen");
Var.modus = new JButton("Modus");
Var.skins = new JButton("Skins");
Var.beenden = new JButton("Beenden");
//Komponenten anpassen
Var.start.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 400, Var.buttonWidth, 50);
Var.optionen.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 500, Var.buttonWidth, 50);
Var.modus.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 600, Var.buttonWidth, 50);
Var.skins.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 700, Var.buttonWidth, 50);
Var.beenden.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 800, Var.buttonWidth, 50);
//Komponenten hinzufügen
Var.frame.getContentPane().add(new DrawStartMenue());
Var.frame.add(Var.start);
Var.frame.add(Var.optionen);
Var.frame.add(Var.modus);
Var.frame.add(Var.skins);
Var.frame.add(Var.beenden);
}
}
package main;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import javax.swing.JPanel;
public class DrawStartMenue extends JPanel{
private static final long serialVersionUID = 1L;
private GridLayout experimentLayout = new GridLayout(6,1);
public Graphics2D g2d;
public void paint(Graphics g) {
//Objekt g zum Zeichnen erzeugen
super.paintComponent(g);
g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//Hintergrund
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, Var.screenWidth, Var.screenHeight);
g2d.setColor(Color.WHITE);
g2d.setStroke(new BasicStroke(8));
g2d.drawRect(Var.whiteRectX1, Var.whiteRectY1 , Var.whiteRectWidth, Var.whiteRectHeight);
//Ball im Hintergrund
for(int i = 0; i < Var.ballList.size(); i++) {
g2d.fillOval(Var.ballList.get(i).ballX, Var.ballList.get(i).ballY,
Var.ballList.get(i).ballWidth, Var.ballList.get(i).ballHeight);
}
//Schriftzug
drawCenteredString(g, "PONG", Var.rect, new Font("NO CONTINUE", Font.PLAIN, 230));
repaint();
}
Var.frame.getContentPane().add(new DrawStartMenue());
Var.frame.add(Var.start);
Var.frame.add(Var.optionen);
Var.frame.add(Var.modus);
Var.frame.add(Var.skins);
Var.frame.add(Var.beenden);
The default layout for a JFrame is the BorderLayout. When you add a component to the frame without specifying a constraint the component is added to the CENTER. Only one component can be added to the CENTER. So only the last one added is visible.
If you want the button on the background then you need to add the buttons to background panel, not the frame:
JPanel background = new DrawStartMenue();
Var.frame.add(background, BorderLayout.CENTER);
background.add(Var.start);
background.add(Var.optionen);
background.add(Var.modus);
background.add(Var.skins);
background .add(Var.beenden);
Other problems with the code:
custom painting is done by overriding paintComopnent(...) not paint(...).
Never invoke repaint() in a painting method. Swing will determine when the component should be repainted.
components should be added to the frame BEFORE the frame is made visible.
don't attempt to setBounds(...) components. Swing was designed to be used with layout managers. Use the appropriate layout manager for your desired layout.
Edit:
So you know how to:
add components to a panel
do custom painting on a panel.
So to combine both concepts you modify the SwingPaintDemo2 code as follow:
//f.add(new MyPanel());
JPanel panel = new MyPanel();
panel.add( new JButton("Testing") );
f.add(panel);
So know that you know the basics, you use the knowledge on your real code.
And don't forget, you should NEVER invoke repaint in a painting method. I already showed you how to use a Swing Timer for the animation.
Next if you don't like the location of the buttons, then you use a different layout manager on the MyPanel class. If you need help with layout manager, then the Swing tutorial also has a section on layout manager with working example for you to download and test.
Here is the MRE. I finally got it to work. However it doesn't work in my project.
package main;
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GUI {
static JFrame frame;
static JPanel buttons;
static JPanel background;
static JButton test1;
static JButton test2;
public static void main(String[] args) {
frame = new JFrame();
frame.setResizable(false);
frame.setSize(600, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Initzialize Components
buttons = new JPanel();
buttons.setBackground(Color.BLACK);
background = new JPanel();
background.setBackground(Color.BLACK);
test1 = new JButton("Test1");
test2 = new JButton("Test2");
//Adding the Buttons
buttons.add(test1);
buttons.add(test2);
//Adding panels to JFrame
frame.add(background);
//frame.add(buttons);
background.add(buttons);
frame.setVisible(true);
}
}

How to add JPanels to JScrollPane?

I'm implementing a simple chat application, using Java. I want my chat application to have the "bubble" message style like modern message apps, so I've built 2 classes LeftArrowBubble and RightArrowBubble which extend JPanel to illustrate sender & receiver bubbles, like this:
This is the code for my LeftArrowBubble class (quite alike for RightArrowBubble):
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JPanel;
/**
* #author harsh
*/
public class LeftArrowBubble extends JPanel {
private static final long serialVersionUID = -5389178141802153305L;
private int radius = 10;
private int arrowSize = 12;
private int strokeThickness = 3;
private int padding = strokeThickness / 2;
#Override
protected void paintComponent(final Graphics g) {
final Graphics2D g2d = (Graphics2D) g;
g2d.setColor(new Color(0.5f, 0.8f, 1f));
int x = padding + strokeThickness + arrowSize;
int width = getWidth() - arrowSize - (strokeThickness * 2);
int bottomLineY = getHeight() - strokeThickness;
g2d.fillRect(x, padding, width, bottomLineY);
g2d.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
g2d.setStroke(new BasicStroke(strokeThickness));
RoundRectangle2D.Double rect = new RoundRectangle2D.Double(x, padding, width, bottomLineY, radius, radius);
Polygon arrow = new Polygon();
arrow.addPoint(20, 8);
arrow.addPoint(0, 10);
arrow.addPoint(20, 12);
Area area = new Area(rect);
area.add(new Area(arrow));
g2d.draw(area);
}
}
Now I have a JFrame window with a JScrollPane on it, which looks like this:
What I want to do now is when I click on that CreateNewBubble button, a new Left(or Right)ArrowBubble JPanel will be created & displayed inside that JScrollPane (and this JScrollPane will be vertical scrollable if there're more bubbles inside of it). I've already tried this way:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
BubbleTest.LeftArrowBubble leftArrowBubble = new BubbleTest.LeftArrowBubble();
jScrollPane1.add(leftArrowBubble);
}
But it didn't work as I expected: nothing shows up in the JScrollPane after clicking the button!
I've been stuck at this problem for hours, really appreciate if you guys can help!
You can't use .add that way on a JScrollPane. A JScrollPane can only scroll a single component, which is set by either passing it to its constructor, or by calling .setViewportView.
Instead, create a separate container for the bubbles, such as a vertical Box, and set that as the single component scrolled by the scroll pane:
Box box = new Box(BoxLayout.Y_AXIS);
JScrollPane jScrollPane1 = new JScrollPane(box);
When you add a bubble, add it to the box (and call .revalidate() to lay it out):
box.add(leftArrowBubble);
box.revalidate();
Edit: Also, your bubbles will not, by default, have any size, unless you give them a size such as by calling setPreferredSize or by overriding getPreferredSize or by putting components inside them.
With JScrollPane you should always add components to the scroll pane's JViewPort. Look at the documentation here, it explains the concept behind the class rather well.
Short summary: A JScrollPane holds the scroll bars and a view port. The view port is a component that displays only a portion of its content - in this case the part that is visible on screen. The scroll bars tell the view port which portion to show.

BoxLayout can't align single element with odd width to center

I am trying to align a number of elements along a vertical axis in the center of a panel, and BoxLayout seems to be just what I need. However, it seems to do strange things when all the elements added have odd-numbered widths.
Here is a SSCCE that demonstrates this screwy behavior:
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.JFrame;
import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.BoxLayout;
import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Component;
public class BoxBug {
public static void main(String[] args){
UIManager.put("swing.boldMetal", Boolean.FALSE);
SwingUtilities.invokeLater(new Runnable(){
public void run(){
gui();
}
});
}
public static void gui(){
JFrame f = new JFrame("Title");
Box b = new Box(BoxLayout.Y_AXIS);
JComponent c = new JComponent(){
public void paint(Graphics g){
g.setColor(new Color(255, 0, 0));
g.fillRect(0, 0, getWidth(), getHeight());
}
// just change the first argument here
// (even numbers work fine, odd ones fail)
private Dimension p = new Dimension(3, 20);
public Dimension getPreferredSize(){return p;}
public Dimension getMinimumSize(){return p;}
public Dimension getMaximumSize(){return p;}
};
c.setAlignmentX(Component.CENTER_ALIGNMENT);
b.add(c);
f.add(b);
f.pack();
f.setVisible(true);
}
}
This is what it looks like:
When I change the width of the JComponent from 3 to 4, it works fine:
Then it fails again when I change the width to 5:
I've searched on Google and StackOverflow for this issue, but haven't found any documentation on this, so it seems to me like a bug.
If it is a bug, can someone find a hack to get around it?
However, it seems to do strange things when all the elements added have odd-numbered widths.
It gets stranger than that. The size of the parent container also affects the layout.
I replaced the f.pack() with:
f.setSize(150, 100);
and it doesn't work. This is basically the scenario you described since this method or the f.pack() will result in the parent container to have an even width and the layout doesn't work.
However, if you use:
f.setSize(151, 100);
the parent container has an odd width and the layout does work properly.
Another strange observation. I tried adding multiple components to the Box. The problem only seems to happen when the last component added has an odd width.
Anyway, I have no idea what the box layout is doing, but it sure seems like a bug to me.
The solution is to use a different layout manager. You can use a GridBagLayout to display components on different rows. You will need to set the constraint for each component to go to a new row.
Or you could try to use the Relative Layout, which support vertical layout with centered alignment and you don't need any constraints. The only change to your code would be:
//Box b = new Box(BoxLayout.Y_AXIS);
JPanel b = new JPanel( new RelativeLayout(RelativeLayout.Y_AXIS) );

AWT Scrollpane scrollbars flash on resize

I am having issues with the java.awt.ScrollPane class's SCROLLBARS_AS_NEEDED display policy handling component resize. Ideally, if I have a ScrollPane that contains a Component that is significantly smaller than the Scrollpane and I shrink the Scrollpane to a size that is still greater than the child component, no scrollbars will appear. However, in practice both scrollbars seem to flicker while the resize operation is occurring and may even persist until the next redraw after the operation completes. Here is a small example to demonstrate what I mean:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.ScrollPane;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Tester implements Runnable{
/**
* #param args
*/
public static void main(String[] args) {
System.setProperty("sun.awt.noerasebackground", "true");
Tester t = new Tester();
SwingUtilities.invokeLater(t);
}
#SuppressWarnings("serial")
#Override
public void run() {
JFrame frame = new JFrame("Tooltip tester");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 800);
Canvas c = new Canvas(){
#Override
public void paint(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
}
};
c.setPreferredSize(new Dimension(400, 400));
ScrollPane s = new ScrollPane();
s.add(c);
frame.add(s);
frame.setVisible(true);
}
}
Shrinking the window in the application above should cause scrollbars to flash. I believe this is caused by a bug in the implementation of the peer of the ScrollPane. (Source Here) I've copied the method that I believe has the error (line 145 in the link).
Dimension getChildSize() {
ScrollPane sp = (ScrollPane)target;
if (sp.countComponents() > 0) {
Component c = sp.getComponent(0);
return c.size();
} else {
return new Dimension(0, 0);
}
}
To me, it seems like the getChildSize() method should call c.getPreferredSize() rather than c.size(). If the ScrollPane child's size is greater than its current preferred size, it should be able to shrink without scroll bars showing up (in my opinion). To test this theory, I overrode the size() method in my example from above:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.ScrollPane;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Tester implements Runnable{
/**
* #param args
*/
public static void main(String[] args) {
System.setProperty("sun.awt.noerasebackground", "true");
Tester t = new Tester();
SwingUtilities.invokeLater(t);
}
#SuppressWarnings("serial")
#Override
public void run() {
JFrame frame = new JFrame("Tooltip tester");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 800);
Canvas c = new Canvas(){
private Dimension prefSize = new Dimension();
#Override
public void paint(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
}
#Override
public void setPreferredSize(Dimension preferredSize) {
prefSize = preferredSize;
super.setPreferredSize(preferredSize);
}
#Override
public Dimension size() {
return prefSize;
}
};
c.setPreferredSize(new Dimension(400, 400));
ScrollPane s = new ScrollPane();
s.add(c);
frame.add(s);
frame.setVisible(true);
}
}
This code behaves exactly how I want it to. However, overriding the size() method to do something other than what the documentation says it should do isn't a particularly elegant way to fix this problem. I feel like I must be doing something wrong here. Is it possible that a fairly basic functionality of the ScrollPane peer for X11 is broken?
A few other related notes:
-Use of java.awt.Canvas is non-negotiable for my purposes. In my actual application, I am drawing something very quickly using Java AWT Native Interface.
-While I read the documentation about new improvements to light/heavyweight compatibility in Java 7 and later versions of Java 6, I didn't really see an improvement in either case so I decided to stick with awt.ScrollPane over swing.JScrollPane. Either way, a ScrollPane should work correctly in the simple case I showed above.
hard to help you without SSCCE, for future readers
However, in practice both scrollbars seem to flicker while the resize operation is occurring and may even persist until the next redraw after the operation completes
used LCD/LED panel caused those flickering (including MsExcell e.g., btw many times discused),
same flickering is for Swing JFrame with JScrollPane
not presented on CRT or Plasma display
if you playing FullHD video on PC, then every good multimedia players waiting until resize ended, thenafter fill available space into its container
you have to add ComponentListener, put there Swing Timer with small delay (KMPlayer show me 350-500milisecs), untill resize continue call for Timer#restart,
Canvas is good workaround for CAD / CAM, OpenGL(CL), good Java video players are based on AWT
you have to avoiding mixing Swing Container with AWT contents, lets everything is based on AWT (undecorated container)

Categories