I want to display an image on a application and when I want to open another one, I want that the new one overwrite the old.
I've looking everywhere to find a solution like use invalidate(), repaint(), etc.. but still not working and I can't figured out why the windows doesn't refresh, can someone help me?
Here the code :
public void actionPerformed(ActionEvent e)
{
System.out.println(e.getActionCommand());
if (e.getActionCommand().contains("Open"))
{
filename_ = new String();
filename_ = JOptionPane.showInputDialog("File to open ?");
ImagePanel test = new ImagePanel(new File(filename_));
test.setPreferredSize(new Dimension(test.getWidth(), test.getHeight()));
test.setMinimumSize(new Dimension(test.getWidth(), test.getHeight()));
test.repaint();
JScrollPane tmp = new JScrollPane();
tmp.getViewport().add(test);
tmp.getViewport().repaint();
mainPanel_.add(tmp, BorderLayout.NORTH);
mainPanel_.repaint();
curim_ = test;
test.memento_ = new Memento(test);
test.caretaker_.add(test.memento_);
curim_ = test;
curmodindex_ = curim_.caretaker_.getIndex();
this.setContentPane(mainPanel_);
System.out.println(curmodindex_);
if (curmodindex_ != 0)
{
button1.setEnabled(true);
button2.setEnabled(true);
}
}
Don't create new components. Just update the data of existing components. Maybe something like:
scrollPane.setViewportView( imagePanel );
Or even easier just use a JLabel to display your image. Then when the image changes you can use:
label.setIcon( new ImageIcon(...) );
Without a proper SSCCE its hard to guess what you are doing wrong. For example I see:
tmp.getViewport().add(test);
...
test.memento_ = new Memento(test);
Without knowing what your code does it looks like you are trying to add the same component to two different components which is not allowed.
Related
I have a simple swing App, that can manage a specific type of project with multiple JButton and that print the project tree on the bottom, see the screenshoot bellow when a project is opened in the App :
App screenshoot with project opened
The thing is when no project is opened I get something like this :
App screenshoot without project opened
The HMI is simple and looks like this :
public class Desktop extends JFrame implements ActionListener {
public Desktop() {
JButton newProject, generate, quit, bAddToClassPath, openProject, saveProject;
JPanel mainPanel;
JScrollPane jscrollpane;
super("MainWindow");
setLookAndFeel();
setSize(330, 440);
ParamMainPanel();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Desktop();
}
});
}
public static void ParamMainPanel() {
mainPanel = new JPanel(new FlowLayout());
// BUTTONS PARAM
newProject = new JButton("Nouveau projet");
generate = new JButton("Générer...");
quit = new JButton("Quitter");
openProject = new JButton ("Ouvrir projet");
saveProject = new JButton ("Sauvegarder");
bAddToClassPath = UIUtil.iconButton();
bAddToClassPath.setActionCommand("setCP");
bAddToClassPath.addActionListener(this);
mainPanel.add(bAddToClassPath);
newProject.addActionListener(this);
newProject.setActionCommand("newP");
generate.addActionListener(this);
generate.setActionCommand("gen");
quit.addActionListener(this);
quit.setActionCommand("qui");
openProject.addActionListener(this);
openProject.setActionCommand("openP");
saveProject.addActionListener(this);
saveProject.setActionCommand("save");
mainPanel.add(newProject);
mainPanel.add(generate);
mainPanel.add(openProject);
mainPanel.add(saveProject);
mainPanel.add(quit);
// PROJECT TREE
jscrollpane = new JScrollPane(new JTree());
jscrollpane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jscrollpane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
jscrollpane.setMinimumSize(new Dimension(50, 50));
jscrollpane.setLocation(4,61);
jscrollpane.setSize(306,322);
mainPanel.add(jscrollpane);
}
}
So what I want is at the App launch, instead of having the bad looking display JTree (into the jscrollpane) without project opened, having the same display with a project opened (white bloc) but without the project tree inside.
I can't figure how to do it, any ideas ?
Here the answer I found to resolve this display problem :
The FlowLayout used on my main panel somehow was preventing me from resizing my jscrollpane directly using setSize()
So I decided to have a secondary panel on my MainFrame secondMainPanel without specific layout using new JPanel(null);
I did add jscrollpaneon it, then I could resize it without problems to have a correct display.
I think there might be better way to fix it, but this one works.
So i have this code
import javax.swing.*;
public class pictest {
public static void main(String[] args) {
JFrame frame = new JFrame("Label Example");
ImageIcon mine = new ImageIcon("C:/Users/Eric/Desktop/mine.jpg");
JLabel pic = new JLabel(mine);
frame.add(pic);
frame.setSize(300,250);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
JFrame framee = new JFrame("Label Example");
ImageIcon minee = new ImageIcon("C:/Users/Eric/Desktop/mine.jpg");
JLabel pice = new JLabel(minee);
framee.add(pice);
framee.setSize(300,250);
framee.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
framee.setVisible(true);
}
}
So when i run the code i get this:
http://imgur.com/a/YF9zt
(the left pic is the code from the top part, the right is the code from the bottom part)
As far as i can tell the code is exactly the same(except for variable names) and i can not figure out why the picture will not show up on the one on the left, is this a problem where i need to reinstall stuff, or is there something in the code that i am just getting wrong.
(also if someone could reformat this post to look right i would appreciate that, sorry i dont use stack overflow much but i was getting frustrated.)
When I try to save your code, I get the following error:
The image shows on the top frame only when I copy
ImageIcon minee = new ImageIcon("C:/Users/Eric/Desktop/mine.jpg");
and paste and edit it to
ImageIcon mine = new ImageIcon("C:/Users/Eric/Desktop/mine.jpg");
I guess you are using some un-recognized charactes in that line.
I've been trying to add JTable to my JPanel, yet it doesn't appear there. I've searched through other questions, but solutions proposed there didn't help me.
The function below is a part of a class which extends JFrame. "repaint" is a BufferedImage, "imageLabel" is JLabel and "image" is ImageIcon.
public void showTable() {
try {
repaint = ImageIO.read(new File("filename.jpg"));
} catch (IOException e) { }
Graphics g = repaint.createGraphics();
g.setFont(font);
g.setColor(black);
String[] columnsName = {"id","text"};
Object[][] data = {{new Integer(1),"text one"},{new Integer(2),"text two"}};
JTable table = new JTable(data, columnsName);
JScrollPane tableContainer = new JScrollPane(table);
image = new ImageIcon(repaint.getScaledInstance(sizeX,sizeY, Image.SCALE_SMOOTH));
imageLabel.setIcon(image);
imageLabel.add(tableContainer,BorderLayout.CENTER);
getContentPane().add(imageLabel);
pack();
setVisible(true);
repaint();
revalidate();
}
What I want to achieve is to display table over loaded image.
Thanks in advance for Your help :)
Give your JLabel a layout manager, here BorderLayout via setLayout(new BorderLayout()).
Don't get your Graphics object via getGraphics() as it returns an object that is short-lived. To see for yourself, minimize your program and then restore it and watch your drawing disappear. Instead, draw in the paintComponent(...) override method.
Read the Swing tutorials for greater detail on how to do these things, especially the layout manager tutorial.
I'm not sure if I understood correctly, but you want to put a table and an image below it, right?
I would create a JPanel with BorderLayout, put the image (JLabel) on the bottom (Page end) and the table (that scrollPanel you created) on the center.
If you need help with adding items to JPanel with BorderLayout, see how to do it on this Tutorial:
http://docs.oracle.com/javase/tutorial/uiswing/layout/border.html
I hope it helps.
Thanks for all the hints so far :) They were really useful. I know that I might be doing some things in a not elegant way, but I'm still learning, will try to improve :)
The given hints and some more searching lead me to such code :
public void showTable()
{
try
{
repaint = ImageIO.read(new File("filename.jpg"));
}catch (IOException e) {
}
Graphics g = repaint.createGraphics();
g.setFont(font);
g.setColor(black);
String[] columnsName = {"id","text"};
Object[][] data = {{new Integer(1),"text one"},{new Integer(2),"text two"}};
JTable table = new JTable(data, columnsName);
table.setOpaque(false);
JScrollPane tableContainer = new JScrollPane(table);
tableContainer.setBorder(BorderFactory.createEmptyBorder());
tableContainer.setOpaque(false);
tableContainer.getViewport().setOpaque(false);
image = new ImageIcon(repaint.getScaledInstance(sizeX,sizeY, Image.SCALE_SMOOTH));
imageLabel.setIcon(image);
imageLabel.setLayout(new BorderLayout());
imageLabel.add(tableContainer, BorderLayout.SOUTH);
repaint();
revalidate();
}
Which works fine for me :)
Once again thanks all for the help :)
I am trying to simply draw an image on a jframe by using an Imageicon. However when I run it its just blank. Heres my code...
public final class PICS
{
public static final void main(String... aArgs)
{
JFrame frame = new JFrame("IMAGE");
frame.setVisible(true);
frame.setSize(500,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ImageIcon image = new ImageIcon("image/pic1.jpg");
JLabel label = new JLabel("", image, JLabel.CENTER);
JPanel panel = new JPanel(new BorderLayout());
panel.add( label, BorderLayout.CENTER );
}
}
I am very new to everything java including this website, so I apologize if im missing something. Also im using Eclipse, and are there specific formats you can use for images, or is there a limit to size?
I am very new to everything java including this website
Then I would suggest you start by reading tutorials especially the Swing tutorial. Maybe the section on How to Use Icons would be a good place to start. The example code will show you how to use Icons as well as how to structure your program so that the GUI code is executed on the EDT. The tutorial on Concurrency will explain why the EDT is important.
Two things.
First, make setVisible the last call AFTER you have built your frame and it's contents...ie
JFrame frame = new JFrame("IMAGE");
frame.setSize(500,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ImageIcon image = new ImageIcon("image/pic1.jpg");
JLabel label = new JLabel("", image, JLabel.CENTER);
JPanel panel = new JPanel(new BorderLayout());
panel.add( label, BorderLayout.CENTER );
// Make me last
frame.setVisible(true);
Two, make sure that the image/pic1.jpg exists and is the directory image under the current execution context.
If the image is a embedded resource (lives within the Jar or your application), then you need to supply a URL to the image instead of a String as ImageIcon treats String as a file name...
ImageIcon image = new ImageIcon(PICS.class.getResource("image/pic1.jpg"));
For example.
I would encourage you to use JFrame#pack over JFrame#setSize as it will resize the frame to the preferred size of your content...
I would also encourage you to take the time to read through Code Conventions for the Java Programming Language, Initial Threads.
I would also encourage you to use ImageIO over ImageIcon as it will, at least, throw an Exception if something goes wrong
Updated, testing image path
Try adding this to the constructor of your PICS class. This will, at least, tell you where the image isn't...
try {
ImageIO.read(PICS.class.getResource("image/pic1.jpg"));
} catch (IOException ex) {
System.out.println("Not in image/pic1.jpg");
}
try {
ImageIO.read(PICS.class.getResource("/image/pic1.jpg"));
} catch (IOException ex) {
System.out.println("Not in /image/pic1.jpg");
}
try {
ImageIO.read(PICS.class.getResource("resources/image/pic1.jpg"));
} catch (IOException ex) {
System.out.println("Not in resources/image/pic1.jpg");
}
try {
ImageIO.read(PICS.class.getResource("/resources/image/pic1.jpg"));
} catch (IOException ex) {
System.out.println("Not in /resources/image/pic1.jpg");
}
a JTabbedPane is just what I need for my purpose.
I have very limited horizontal space, so my Tabs get stacked, which is perfectly ok.
But the default behaviour is that if user clicks on a Tab, the *Tabs get re-sorted so that the active Tab becomes the lower-mos*t. What looks very intuitive and logical in theory, is a nightmare in practical use, because the users loose track of "which was which". Its just simply plain confusing, I am told again and again.
I guess it should be possible to override some method of the UI to avoid this behaviour (and I dont care whether this would be physically possible with paper cards :-) .
Has anyone any idea where I need to do that? I am using Nimbus LAF, which does not seem to make it easier.
(I thought about using radiobuttons/cardLayout, but I need to put a custom panel in the tab title, and radiobuttons can only have a string or icon. Same for JToggleButton...)
Any hints are greatly welcome!
Thanks & Kind regards,
Philipp
sscce for potential answerer(s) for Nimbus L&f (by using another L&f isn't possible to reproduce this funny issue), in case that Containers#Size packed Tabs to the two or more Lines,
as I know there is only one possible solutions (without override NimbusTabbedPaneUI) by aephyr
from sscce
import java.awt.BorderLayout;
import javax.swing.*;
public class TabbedPane {
private static final long serialVersionUID = 1L;
public TabbedPane() {
JPanel jp = new JPanel();
jp.setLayout(new BorderLayout());
JTabbedPane tb = new JTabbedPane();
//tb.setUI(new CustomTabbedPaneUI());
tb.add("Tab1", new JTextArea(10, 20));
tb.add("Tab2", new JTextArea(10, 20));
tb.add("Tab3", new JTextArea(10, 20));
tb.add("Tab4", new JTextArea(10, 20));
tb.add("Tab5", new JTextArea(10, 20));
jp.add(tb, BorderLayout.CENTER);
//add(jp, BorderLayout.CENTER);
//tb.setEnabledAt(1, false);
//tb.setEnabledAt(3, false);
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(jp, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception system) {
system.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TabbedPane tP = new TabbedPane();
}
});
}
}
Okay, I found the Problem. In
package javax.swing.plaf.basic.BasicTabbedPaneUI;
it says something like this
// Rotate run array so that selected run is first
if (shouldRotateTabRuns(tabPlacement)) {
rotateTabRuns(tabPlacement, selectedRun);
}
Its a pity that there seems to be no easy set-a-flag-and-there-you-go-way is for changing that.
Although you should be fine if you omitted the call to rotateTabRuns(tabPlacement, selectedRun); or change shouldRotateTabRuns(tabPlacement) for that matter... however, to do so you would have to override a whole bunch of classes... depending on which plaf you use.
It inherits like this
Basic > Synth > Nimbus
And on each L&F-level there are several classes to customize... I didn't count.
Hope it helps! :D
Edit
Oh yeah... #mkorbel already provided sort of the solution with this aephyr why not use that?
It's a bit of a hack but you can override the Nimbus defaults to have the plain old Java look-and-feel for the tabbed pane, whilst keeping everything else the same. The plain Java look-and-feel for a tabbed pane doesn't do the annoying reordering. Just store the defaults before you set the look-and-feel and then set them back.
// get the defaults to keep
HashMap<Object, Object> defaultsToKeep = new HashMap<>();
for (Map.Entry<Object, Object> entry : UIManager.getDefaults().entrySet()) {
boolean isStringKey = entry.getKey().getClass() == String.class ;
String key = isStringKey ? ((String) entry.getKey()):"";
if (key.startsWith("TabbedPane")) {
defaultsToKeep.put(entry.getKey(), entry.getValue());
}
}
// set nimbus look and feel
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
// set back your originals
for (Map.Entry<Object, Object> entry : defaultsToKeep.entrySet()) {
UIManager.getDefaults().put(entry.getKey(), entry.getValue());
}
JFrame.setDefaultLookAndFeelDecorated(true);