Very strange Java2D effect setClip () - error?

I want to create a dialogue with a customizable shape and transparency, think that the information bubble points to some component.

To do this, I add a JPanel to JDialog and overwrite the panel's paintComponent(Graphics) method. The panel itself contains regular JLabels and JButtons . Works great, but as soon as I use Graphics2D.setClip(Shape) in the panel drawing code, the components are overloaded with the background. If I do not set the clip (for a completely new Graphics2D object, not less), everything works fine. This is very puzzling to me, and I have no idea what I can do to fix it.

PS: I can not use setShape(Shape) in JDialog , because there is no smoothing. PPS: The actual Usecase is to draw a large background image that needs to be cropped exactly in the shape of an information bubble.

The following SSCCE demonstrates the problem when you press the "x" in the upper right corner several times.

 import java.awt.BorderLayout; 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.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextArea; import java.awt.Polygon; import java.awt.Shape; public class Java2DTransparencySSCE extends JDialog { JPanel panel; private JButton close; private JLabel headline; private JLabel mainText; public Java2DTransparencySSCE() { setLayout(new BorderLayout()); setFocusable(false); setFocusableWindowState(false); setUndecorated(true); setBackground(new Color(0, 0, 0, 0)); panel = new JPanel(new GridBagLayout()) { @Override public void paintComponent(final Graphics g) { super.paintComponent(g); Graphics2D gImg = (Graphics2D) g.create(); // if the line below is removed, everything works.. Shape oldClip= gImg.getClip(); // both the shape and a standard rectangular clip break everything // gImg.setClip(50, 50, 50, 50); Polygon shape = new Polygon(new int[] {0, 100, 100, 50, 0}, new int[] {200, 200, 100, 50, 100}, 5); gImg.setClip(shape); gImg.setColor(new Color(255, 0, 0, 50)); gImg.fill(shape); gImg.setClip(oldClip); gImg.dispose(); } }; panel.setOpaque(false); add(panel, BorderLayout.CENTER); headline = new JLabel("This is a title"); mainText = new JLabel("<html><div style=\"line-height: 150%;width:100px \">This is some sort of text which is rather long and thus pretty boring to actually read. Thanks for reading anyway!</div></html>"); close = new JButton("X"); close.setBorderPainted(false); close.setContentAreaFilled(false); close.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.exit(0); } }); layoutPanel(); } private void layoutPanel() { GridBagConstraints constraints = new GridBagConstraints(); constraints.gridx = 0; constraints.gridy = 0; constraints.insets = new Insets(10, 10, 10, 10); constraints.fill = GridBagConstraints.BOTH; constraints.weightx = 1; panel.add(headline, constraints); constraints.gridx += 1; constraints.weightx = 0; constraints.fill = GridBagConstraints.NONE; panel.add(close, constraints); constraints.gridx = 0; constraints.gridy += 1; constraints.gridwidth = 2; constraints.weightx = 1; constraints.weighty = 1; constraints.fill = GridBagConstraints.BOTH; panel.add(mainText, constraints); pack(); } public static void main(String[] args) { JFrame parent = new JFrame(); JPanel pane = new JPanel(new BorderLayout()); pane.add(new JTextArea("This is a text.")); parent.setContentPane(pane); parent.setSize(400, 400); parent.setLocation(400, 300); parent.setDefaultCloseOperation(JDialog.EXIT_ON_CLOSE); parent.setVisible(true); JDialog dialog = new Java2DTransparencySSCE(); dialog.setLocation(500, 400); dialog.setAlwaysOnTop(true); dialog.setVisible(true); } } 

EDIT: To get around this error on Windows, I added the following, which did not cause problems or performance impacts in my use case (may be different for you):

 JDialog dialog = new Java2DTransparencySSCE() { @Override public void paint(Graphics g) { g.setClip(null); super.paint(g); } }; 
+6
source share
4 answers

When mousing over JButton panel redraws itself only with the borders necessary for redrawing - button restrictions (if you check oldClip , these should be JButton borders). Changing the borders of the clips causes the alpha colors to be composite for each previous paint call, because the clip is not cleared super.paintComponent And the background of JDialog is completely transparent.

I want to create a dialogue with a customizable shape and transparency, think that the information bubble points to some component.

Consider using a lightweight component - you can do this by installing a JFrame glass panel containing dialog elements, and if necessary, switching the visibility and / or contents of the glass panel.

0
source

You must save the original clip before your custom drawing and restore it after.

 Shape oldCLip=g2d.getClip(); ... your code ... g2d.setClip(oldClip); 
+1
source

In Mac OS X 10.9, Java 8, I do not see anomalies. I see an identical appearance with the option below, in which the derived graphic context is not created or placed. The API assumes that "programmers should call dispose when they are finished using the Graphics object only if it was created directly from a component or another Graphics object." I'm not sure how implementations differ internally, but this can be a criminal.

image

 @Override public void paintComponent(final Graphics g) { super.paintComponent(g); Graphics2D gImg = (Graphics2D) g; Shape oldClip= gImg.getClip(); Polygon shape = new Polygon( new int[] { 0, 100, 100, 50, 0}, new int[] {200, 200, 100, 50, 100}, 5); gImg.setClip(shape); gImg.setColor(new Color(255, 0, 0, 50)); gImg.fill(shape); gImg.setClip(oldClip); } 
+1
source

You should call super.paintComponent (g) after all the drawing code (this will be the last line of your redefinition).

Thus, your drawing will be below child components.

-1
source

Source: https://habr.com/ru/post/988949/


All Articles