Painting on a JPanel and adding it to a JScrollPane - java

As the title suggests, i want to paint on a JPanel and have it displayed within a JScrollpane so if the contents in the JPanel is large, scrollbars are displayed. I tried to accomplish this by:
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class Main extends JFrame{
DrawPanel dp;
JScrollPane jsp;
public Main(){
setTitle("Test");
setSize(400,400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
dp = new DrawPanel();
jsp = new JScrollPane(dp);
getContentPane().add(jsp);
}
public class DrawPanel extends JPanel{
#Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
Graphics2D g2d = (Graphics2D) grphcs;
g2d.drawString("..long text....long text....long text....long text....long text....long text....long text....long text..", 10, 20);
}
}
public static void main(String[] args) {
new Main().setVisible(true);
}
}
Current Output
Expected Output: A window with the long text and horizontal scrollbar.
I have also tried overriding the getPreferredSize method (as some answers in other questions suggested) but it doesn't seem to work.
Also, can someone explain why scrollbars appear (using jscrollpane) when there are labels or buttons in a panel which is added to the jscrollpane, but the same doesn't work in the case above? Any help will be much appreciated.

You can resize a JPanel via setting the size(s) or overriding them.
Dimension d = new Dimension(800, 800);
dp.setMinimumSize(d);
dp.setMaximumSize(d);
dp.setPreferredSize(d);
Scroll bars appear when I do that.

Related

how to do auto-resizing drawings in JPanel?

what's the easiest way to have a drawing in a JPanel that resizes whenever the user resizes the JFrame?
I know that I can auto resize the panel with a BorderLayout but the drawings are not resized in this case. I am new to java and GUI programming and there are probably numerous solutions.
please give me a hint into the right direction to make e.g. the rectangle in
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.*;
public class DrawRect extends JPanel {
#Override
protected void paintComponent(Graphics g) {
g.drawRect(20, 20, 100, 100);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
DrawRect panel = new DrawRect();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(200, 200));
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
auto-resizing whenever the frame is resized.
Provide positions and sizes as a proportion of the width and height of the panel. Whenever the panel is resized, the rendering engine will schedule a call to the paintComponent() method and the rectangle will be drawn proportionally. E.G.
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.*;
public class DrawRect extends JPanel {
#Override
protected void paintComponent(Graphics g) {
int w = getWidth();
int h = getHeight();
g.drawRect(w/10, h/10, w/2, h/2);
}
/* A custom component should give the layout manager hints as to
its preferred size. */
#Override
public Dimension getPreferredSize() {
return new Dimension(200,200);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
DrawRect panel = new DrawRect();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
frame.getContentPane().setLayout(new BorderLayout());
Insert the line before you add the component to the GUI.
You should study layoutmanagers, since it is a unique concept in Java.

Java Swing Scroll through drawing

Im trying to add a JScrollpane to my JPanel. The problem is that the scrollpane doesn't recognize that my drawing is outside the frame. So how do I add the JScrollpane correctly?
Main class:
public MainFrame() extends JFrame{
public MainFrame() {
Container container = getContentPane();
container(new BorderLayout());
container.add(new JScrollPane(new Drawing()));
setSize(1280,720);
setVisible(true);
}
Drawing class:
public class Drawing() extends JPanel {
#Override
protected void paintComponent(Graphics g) {
g.drawLine(10, 100, 30000, 10);
}
}
There are a couple of errors in your code, let's step through each of them:
You're extending JFrame, and you should avoid it, see: Extends JFrame vs. creating it inside the program for more information about it. You're actually not changing its behavior so it's not needed to extend it.
For your JScrollPane to show the whole line, you need to change your window's size to be the same size of your line (as shown in this answer by #MadProgrammer).
Related to point 2, avoid the use of setSize(...) and instead override getPreferredSize(): See Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? for more information
You forgot to call super.paintComponent(...) method in your paintComponent() method.
Related to points 2, 3, you need to call pack() so Swing calculates the best preferred size for your component.
See this example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class LongDraw {
private JFrame frame;
private Drawing drawing;
public static void main(String[] args) {
SwingUtilities.invokeLater(new LongDraw()::createAndShowGui);
}
private void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
drawing = new Drawing();
JScrollPane scroll = new JScrollPane(drawing);
frame.add(scroll);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class Drawing extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawLine(10, 100, 3000, 10);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(3000, 500);
}
}
}
Which produces something similar to this:

java graphics2D inside JPanel

I am trying to draw some simple shapes onto a JPanel but am having some difficulty. Apologies if this question appears to have been answered before but the other answers don't seem to help.
I followed a simple tutorial and was successful in drawing some basic shapes onto a JFrame, but when I moved the code how it was into a new class which extends JPanel, nothing appears on screen.
public class TestingGraphics extends JFrame{
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
new TestingGraphics();
}
public TestingGraphics(){
this.setSize(1000,1000);
this.setPreferredSize(new Dimension(1000,1000));
this.setTitle("Drawing tings");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(new TestingPanelGraphics(), BorderLayout.CENTER);
this.setVisible(true);
}
public class TestingPanelGraphics extends JPanel {
public TestingPanelGraphics(){
this.setSize(1000,1000);
this.setPreferredSize(new Dimension(1000,1000));
this.add(new DrawStuff(), BorderLayout.CENTER);
revalidate();
repaint();
this.setVisible(true); //probably not necessary
}
private class DrawStuff extends JComponent{
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D graph2 = (Graphics2D) g;
graph2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Shape rootRect = new Rectangle2D.Float(100, 100, 1000, 500);
graph2.setColor(Color.BLACK);
graph2.draw(rootRect);
}
I've tried setting preferred size, and revalidating and repainting.
I've added a call to super.paintComponent, although neither of those two were necessary when I was drawing straight onto a JFrame.
I ensured I was overriding paintComponent and changed it from public to protected. All following advice from similar threads, but nothing seems to work. I've stepped through in debugger mode and ensured it goes into the right method, and even watched it go into the paintManager, but still nothing appears on the window.
You've forget to set the appropriate layout manager.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestingGraphics extends JFrame{
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
new TestingGraphics();
}
public TestingGraphics(){
this.setSize(1000,1000);
this.setPreferredSize(new Dimension(1000,1000));
this.setTitle("Drawing tings");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(new TestingPanelGraphics(), BorderLayout.CENTER);
this.setVisible(true);
}
public class TestingPanelGraphics extends JPanel {
public TestingPanelGraphics(){
setLayout(new BorderLayout());
this.setPreferredSize(new Dimension(1000,1000));
this.add(new DrawStuff(), BorderLayout.CENTER);
revalidate();
repaint();
this.setVisible(true); //probably not necessary
}
private class DrawStuff extends JComponent{
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D graph2 = (Graphics2D) g;
graph2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Shape rootRect = new Rectangle2D.Float(100, 100, 1000, 500);
graph2.setColor(Color.BLACK);
graph2.draw(rootRect);
}
}
}
}
When you extends JFrame your default layout is the BorderLayout, but when you extends JPanel your default layout is the FlowLayout.

arrange non rectangular JPanels in Java Swing

I've defined a new class LShapePanel which extends JPanel and which looks like an L.
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
public class LShapePanel extends JPanel{
public Color color;
public LShapePanel(Color color) {
this.color = color;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(color);
/* coordinates for polygon */
int[] xPoints = {0,100,100,20,20,0};
int[] yPoints = {0,0,20,20,100,100};
/* draw polygon */
g2d.fillPolygon(xPoints, yPoints, 6);
}
}
I'd like to arrange two of these LShapePanels like this:
But I don't know how? Here is my code for arranging two LShapePanels in a row.
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Dimension;
public class DifferentShapes extends JFrame {
public DifferentShapes() {
setTitle("different shapes");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocation(500, 300);
JPanel panel = new JPanel();
/* create and add first L in red */
LShapePanel lsp1 = new LShapePanel(new Color(255,0,0));
lsp1.setPreferredSize(new Dimension(100,100));
panel.add(lsp1);
/* create and add second L in green*/
LShapePanel lsp2 = new LShapePanel(new Color(0,255,0));
lsp2.setPreferredSize(new Dimension(100,100));
panel.add(lsp2);
add(panel);
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
DifferentShapes df = new DifferentShapes();
df.setVisible(true);
}
});
}
}
And the result:
You need to use layout manager to arrange the components in the JFrame. According to this turorial, the content pane, which actually contains the components you put into JFrame, uses Borderlayout by default. In an "L" shape as the LShapePanel looks, it's actually a rectangle(every component in swing is a rectangle, as a matter of fact) with part of it transplant. So if you want to arrange the panels in the way you want, they will have to overlap with each other. Different kinds of layout managers use different layout strategies, and Borderlayout won't allow components to overlap, so you have to change to another layout manager. Sorry that I don't know any layout manager that allows components to overlap, but you can use JLayeredPane to achieve you goal. Add a JLayeredPane to the JFrame and then add the LShapePanels to the JLayeredPane.
Sorry, layout manager enthusiasts, but I can't think of any way other than using setLocation and a null layout manager. Here's a demonstration:
setLayout(null);
LShapePanel lsp1 = new LShapePanel(new Color(255,0,0));
lsp1.setPreferredSize(new Dimension(100,100));
lsp1.setLocation(0,0);
add(lsp1);
LShapePanel lsp2 = new LShapePanel(new Color(0,255,0));
lsp2.setPreferredSize(new Dimension(100,100));
lsp2.setLocation(30,30);
add(lsp2);

How do I draw over top of a JScrollPane?

I have a JScrollPane that fills a JPanel (which is the content pane for my JFrame). The JPanel performs custom drawing - however, it doesn't appear over top of the JScrollPane. Should I override something other than paintComponent?
Here is a demo:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.LayoutManager;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// Create the frame.
JFrame frame = new JFrame();
frame.setPreferredSize(new Dimension(1024, 768));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel custom = new CustomPanel(new BorderLayout());
// Add the scroll pane.
JScrollPane scroll = new JScrollPane();
scroll.setBorder(BorderFactory.createLineBorder(Color.blue));
custom.add(scroll, BorderLayout.CENTER);
// Display the frame.
frame.setContentPane(custom);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
#SuppressWarnings("serial")
class CustomPanel extends JPanel {
public CustomPanel(LayoutManager lm) {
super(lm);
}
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.red);
g.drawRect(200, 200, 200, 200);
}
}
I'd like for the paint on the JPanel to go over top of the paint on
the JScrollPane
you can to paint to the
JViewport as you can to see here and here
use JLayer(Java7) based on JXlayer(Java6)
very similair (as todays JLayer) is painting to GlassPane, notice GlassPane to consume()(by default) MouseEvent in the case there is(are) added some JComponent(s), GlassPane can to covers whole RootPane or only part of available Rectangle, depends of used LayoutManager and Dimension returns from layed JComponent(s)
Just a simple problem. You are adding the scrollpane to the custompanel which is hiding what your are drawing. Instead, consider intializing your scrollpane with the cutsompanel as its content.
Example:
JScrollPane scrlPane = new JScrollPane(customPanel);
when you add a single component to a BorderLayout and specify BorderLayout.CENTER, the component will expand to completely fill its parent. If the component is opaque, you won't be able to see any custom painting you are doing in the parent.
The way that worked (as #mKorbel suggested) is to play with the JViewport:
scroll.setViewport(new CustomViewPort());
where CustomViewPort is a class extending JViewport that overrides the paintComponent method.

Categories

Resources