I've created a custom JPanel that has background with diagonal lines fixed or animated. I wondered that if I add any jcomponent to panel, it is not shown at all. I understand that problem is because I paint over components, but I don't know how solve it. Here is my complete code.
Some help will be appreciated :)
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import javax.swing.JPanel;
import javax.swing.Timer;
public class JStripedPanel extends JPanel {
int space = 20;
float thickness = 2f;
int xpos = 0;
float progress = 0f;
Float th = 2f;
int dir = 1;
Timer timer;
Timer cbt = null;
Paint lineColor = new Color(255,50,50,50);
public JStripedPanel() {
super();
}
public JStripedPanel(LayoutManager l) {
super(l);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(getBackground());
g2.fill(getShape());
//g2.setClip(getShape());
if(thickness > 0) {
// draw diagonal lines
g2.setPaint(getLineColor());
g2.setStroke(new BasicStroke(thickness));
int h = 0;
int max = Math.max(this.getSize().width, this.getSize().height) getSpace();
int x = - max - getSpace();
while( x < this.getSize().width getSpace() ) {
g2.drawLine(xpos x, max, xpos x max, h);
x = getSpace();
}
}
// g2.setColor(Color.black);
// g2.setStroke(new BasicStroke(5));
// g2.drawLine(0, this.getSize().height/2, this.getSize().width, this.getSize().height/2);
g2.dispose();
}
public void setLineColor(Paint lineColor) {
this.lineColor = lineColor;
}
private Paint getLineColor() {
return lineColor;
}
public void setStripe(int space, float thikness) {
this.space = space;
this.thickness = thikness;
}
public int getSpace() {
return space;
}
private void setXpos(int xpos) {
if(xpos > getSpace())
xpos = 0;
this.xpos = xpos;
}
private int getXpos() {
return xpos;
}
private Shape getShape() {
Shape s = new Rectangle(getBounds());
return s;
}
public void startAnim(float thickness) {
this.thickness = thickness;
timer = new Timer(100, (e) -> {
setXpos(getXpos() 1);
repaint();
setStripe(20, th);
th = th = .5f * dir;
if(th > 35.5f)
dir = -1;
else if(th < 1.5f)
dir = 1;
});
timer.start();
}
public void stopAnim(boolean now) {
if(now) {
stopNow();
return;
}
try {
cbt = new Timer(50, (e) -> {
timer.setDelay(timer.getDelay() 150);
if(thickness > 0) {
thickness -= 0.5f;
}
repaint();
if(timer.getDelay() >= 2500) {
cbt.stop();
cbt = null;
return;
}
});
cbt.start();
} catch (Exception e) { }
stopNow();
}
public void stopNow() {
if(timer != null)
timer.stop();
timer = null;
thickness = 0;
System.gc();
}
public static void main(String[] args) throws InterruptedException {
// this panel works!
// JPanel t = new JPanel(new FlowLayout(FlowLayout.LEADING, 5, 5));
// my panel don't
JStripedPanel t = new JStripedPanel(new FlowLayout(FlowLayout.LEADING, 5, 5));
t.setBackground(Color.pink);
t.setOpaque(true);
t.setBorder(
javax.swing.BorderFactory.createCompoundBorder(
new javax.swing.border.EmptyBorder(1, 1, 1, 1),
new javax.swing.border.LineBorder(Color.blue, 2, true))
);
t.add(new javax.swing.JLabel("test"));
t.add(new javax.swing.JTextField("test2"));
javax.swing.JFrame f = new javax.swing.JFrame();
f.setBounds(10,10,400,300);
// f.getContentPane().setLayout(new java.awt.GridLayout(3,3));
// f.getContentPane().add(javax.swing.Box.createHorizontalGlue());
// f.getContentPane().add(javax.swing.Box.createHorizontalGlue());
// f.getContentPane().add(javax.swing.Box.createHorizontalGlue());
// f.getContentPane().add(javax.swing.Box.createHorizontalGlue());
f.getContentPane().add(t, java.awt.BorderLayout.CENTER);
// f.getContentPane().add(javax.swing.Box.createHorizontalGlue());
// f.getContentPane().add(javax.swing.Box.createHorizontalGlue());
f.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
t.startAnim(2);
Thread.sleep(10000);
t.stopAnim(false);
Thread.sleep(5000);
t.startAnim(2);
}
}
CodePudding user response:
Remove the call to g2.dispose()
and it will work like a charm. You should not dispose it as, that same Graphics
object is used further to draw the components inside the panel.
The main painting method works like this:
public void paint(Graphics g) {
paintComponent(g);
paintBorder(g);
paintChildren(g);
}
Thus disposing the graphics in paintComponent
makes it non-functional into the next paintxxx
methods.
In a more general way of thinking, you should not clear/dispose/close any object you don't have the ownership. Someone creates the Graphics
, pass it to you , you can use it (that's the purpose), but not dispose it. It is the responsability of the one that creates it.