java scrolling while dragging - java

So I have several problems:
1) Is this code OK ? Or can it be written better ? (I will have an array with pictures in the final version)
2) When I click Next button the rectangle that I drew on first picture stays on the second one, how to clear it ? So after pressing Next button there is no rectangle on the new picture ?
3) I want to be able to auto-scroll while I drag the mouse button (while drawing the rectangle), but it's not really working...
Please help
public class SelectionExample {
static public TestPane panelek;
static public BufferedImage tempimage;
public static void main(String[] args) {
new SelectionExample();
}
public SelectionExample() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
panelek = new TestPane();
panelek.setPreferredSize(new Dimension(100, 100));
panelek.setAutoscrolls(true);
JScrollPane scrollPane = new JScrollPane(panelek);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
frame.add(scrollPane, BorderLayout.CENTER);
JButton next = new JButton("NEXT");
frame.add(next, BorderLayout.PAGE_START);
try {
tempimage = ImageIO.read(new File("D:/test/temp1.jpg"));
} catch (IOException ex) {
Logger.getLogger(SelectionExample.class.getName()).log(Level.SEVERE, null, ex);
}
next.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
try {
tempimage = ImageIO.read(new File("D:/test/temp2.jpg"));
} catch (IOException ex) {
Logger.getLogger(SelectionExample.class.getName()).log(Level.SEVERE, null, ex);
}
panelek.repaint();
}
});
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

Is this code OK ? Or can it be written better ?
Don't use static variables. If you want to change the image on your panel then you need to create a setImage(...) method in your class. The method will then save the image and invoke repaint(). That is classes should be responsible for managing their properties and provide getter/setter methods.
The formatting of your code is terrible and therefore difficult to read. Use either tabs or spaces for code indentation and be consistent.
I want to be able to auto-scroll while I drag the mouse button
Read the API for the setAutoScrolls(...) method of the JComponent class. It provides code for the mouseDragged(...) method of your MouseMotionLister.

Related

How can a JPanel be changed after added to JFrame?

I have created a subclass of JPanel to display images. I instantiate this in the constructor of a JFrame and add it to that JFrame. This works perfectly. Then I have added a button with an ActionListener to change that Image. My problem is that the JFrame won´t update although I have tried repainting etc.
The subclass of JPanel:
public class ImagePanel extends JPanel {
BufferedImage bf;
public ImagePanel(String dateiname)
{
try {
bf = ImageIO.read(new File(dateiname));
} catch (IOException e) {
e.printStackTrace();
}
}
public void paint(Graphics g)
{
g.drawImage(bf.getScaledInstance(300,200,1),0,0,null );
}
}
The JFrame is basically this
public class Hauptfenster extends JFrame {
private JButton changeImage;
private JPanel buttonPanel;
private ImagePanel ip;
public Hauptfenster {
ip = new ImagePanel("first_image.jpg");
buttonPanel = new JPanel();
buttonPanel.add(changeImage);
changeImage.addActionListener((e) -> {
ip = new ImagePanel("new_image.jpg");
ip.setVisible(true);
});
this.add(buttonPanel);
this.add(ip);
this.setVisible(true);
}
}
Why doesn´t the method in the ActionListener update the ip component in the JFrame Hauptfenster?
When you do ip = new ImagePanel("new_image.jpg"); you're creating a whole new ImagePanel that has nothing to do with your current layout. You could.
remove(ip);
ip = new ImagePanel("new_image.jpg");
add(ip);
repaint();
Another way you could do it is to just change the buffered image.
Add the following method to your image panel.
public void loadImage(String dateiname) {
try {
bf = ImageIO.read(new File(dateiname));
} catch (IOException e) {
e.printStackTrace();
}
}
Then in your action listener.
ip.loadNewImage("new_image.jpg");
ip.repaint();
You have a bunch of bad habits going on in your code though.
Such as, override paintComponent instead of paint and it should look like.
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(bf.getScaledInstance(300,200,1),0,0,null );
}
That way transparency will be handled correctly.
You shouldn't extend JFrame, you should just create a JFrame.
When you add components, you there is a layout manager involved. It's good to be aware of that and handle things accordingly. I would change your constructor to.
public Hauptfenster() {
JFrame frame = new JFrame();
ip = new ImagePanel("first_image.jpg");
buttonPanel = new JPanel();
changeImage = new JButton("change image");
buttonPanel.add(changeImage);
changeImage.addActionListener((e) -> {
frame.remove(ip);
ip = new ImagePanel("new_image.jpg");
frame.add(ip, BorderLayout.CENTER);
frame.repaint();
});
frame.add(buttonPanel, BorderLayout.SOUTH);
frame.add(ip, BorderLayout.CENTER);
frame.setVisible(true);
}
If you need more help, you'll need to actually make your example compilable. There are too many errors right now.

Nimbus - override color for TableHeader

I would like to override the background color of headers in JTables when using the Nimbus L&F. I'm effectively "theming" the Nimbus L&F, i.e. making small adjustments to it.
Whatever I try it doesn't seem to have effect.
Here's an SSCCS :
public class MyTest {
public static void main(String[] args) {
new MyTest();
}
public MyTest() {
try {
UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
Logger.getLogger(MyTest.class.getName()).log(Level.SEVERE, null, ex);
}
UIManager.put("TableHeader.background", Color.RED);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
DefaultTableModel model = new DefaultTableModel(
new Object[][]{
{"hhvt ", "er sdf", "sfdg"},
{"hyshg ", "dh sdf", "jer"}
},
new Object[]{"Col A", "Col B", "Col C"}
);
JTable table = new JTable(model);
setLayout(new BorderLayout());
add(new JScrollPane(table));
}
}
}
Here's the result:
I'm well aware that Nimbus is a Synth L&F so it uses Painters for just about anything. I bet I could override some Painter in UIManager but I don't want to redo a Painter from scratch. The Painters in Nimbus are quite advanced, they use gradients and what have you. I would like to take advantage of that. It's just the color I would like to change.
Here's a possible - but quite ugly - solution.
Nimbus relies heavily on Painters. The reason why Nimbus looks good is because it uses gradients, shadows and what not. That's the job of the Painter. We really, really don't want to do our own Painters. The Nimbus Painters are quite complex and produce beautiful results. So we want to leverage them. Not do them ourselves!
Nimbus has a lot of auto-generated source code. All source code is generated off the skin.laf XML file (which is in the JDK source) but the XML file is not used at runtime. Most of the auto-generated source files are in fact type-specific Painters. For example there's a painter class for TableHeaderRendererPainter (a painter responsible for painting table headers) and so on. The problem is that all auto-generated source code is package-private.
Painters are set when an instance of NimbusLookAndFeel is initialized. They don't change after this.
From skin.laf file we can see what colors are used for what. In our case we can see it's really the nimbusBlueGrey color that governs the background color of the table headers. We can't just change the value of nimbusBlueGrey as that would affect everything in Nimbus that uses this color. So we need to come up with something else. And this is where it gets ugly.
In the specific case we're interested in table headers as they look by default (i.e. when the mouse is not over them, the table is not disabled, the column header is not pressed, etc). So this is what we'll concentrate on below. But the technique would be the same for any other type of special decoration that somebody would want to do.
The technique is to first start up a temporary instance of the NimbusLookAndFeel. We do this only so we can 'steal' one of the Painters it has generated. We than safe keep this Painter and then start the NimbusLookAndFeel for real. Now we can replace our specific Painter so that we swap in the one we saved previously.
public class MyTest {
public static void main(String[] args) throws UnsupportedLookAndFeelException {
new MyTest();
}
public MyTest() throws UnsupportedLookAndFeelException {
// Start dummy instance of L&F
NimbusLookAndFeel nimbusTmp = new NimbusLookAndFeel();
Object nimbusBlueGreyOrg = UIManager.get("nimbusBlueGrey"); // original value
UIManager.put("nimbusBlueGrey", Color.RED); // the color we want
try {
UIManager.setLookAndFeel(nimbusTmp);
} catch (UnsupportedLookAndFeelException ex) {
Logger.getLogger(MyTest.class.getName()).log(Level.SEVERE, null, ex);
}
Object painter = UIManager.get("TableHeader:\"TableHeader.renderer\"[Enabled].backgroundPainter");
// We've got what we came for. Now unload the dummy.
UIManager.getLookAndFeel().uninitialize(); // important to avoid UIDefaults change listeners firing
UIManager.put("nimbusBlueGrey", nimbusBlueGreyOrg); // revert
// Load the L&F for real.
UIManager.setLookAndFeel(new NimbusLookAndFeel());
// Swap in the value we saved previously
UIManager.put("TableHeader:\"TableHeader.renderer\"[Enabled].backgroundPainter", painter);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
DefaultTableModel model = new DefaultTableModel(
new Object[][]{
{"hhvt ", "er sdf", "sfdg"},
{"hyshg ", "dh sdf", "jer"}},
new Object[]{"Col A", "Col B", "Col C"}
);
JTable table = new JTable(model);
setLayout(new BorderLayout());
add(new JScrollPane(table));
}
}
}
Not proud of this, but it works. Anyone with better ideas ?

JLayeredPane with a JDialog

I am unable to make any components apear on a JLayeredPane when adding it to a JDialog.
I have also been unable to find a web resource that shows this may be done in a reasonably sized block of code. Every sight iv looked at "claims" this can be done, and then shows a disgustingly long solution.
What i want is to take a JLayered pane add a Button and place a JLabel with an icon in it onto this pane aswell. In english i want a button with an icon stuck in the front of its text.
That is the awt Button as I have been unable to find a way of making a system looking swing JButton.
Edit: could you help me out with something a little more specific. I think I was a littile to vague in my post.
Button button = new Button("ok");
JDialog dialog = new JDialog(null,"Windows",Dialog.ModalityType.APPLICATION_MODAL);
dialog.getLayeredPane().add(button);
dialog.pack();
dialog.setVisible(true);
I don't seem to have any issues...
public class TestLayeredDialog {
public static void main(String[] args) {
new TestLayeredDialog();
}
public TestLayeredDialog() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JDialog dialog = new JDialog();
dialog.setModal(true);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setLayout(new BorderLayout());
dialog.add(new MyContent());
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
System.exit(0);
}
});
}
public class MyContent extends JLayeredPane {
public MyContent() {
JLabel label = new JLabel("Hello new world");
label.setSize(label.getPreferredSize());
label.setLocation(0, 0);
add(label);
Dimension size = getPreferredSize();
JButton button = new JButton("Click me");
button.setSize(button.getPreferredSize());
button.setLocation(size.width - button.getWidth(), size.height - button.getHeight());
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.getWindowAncestor(MyContent.this).dispose();
}
});
add(button);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Remember, JLayeredPane DOES NOT have a layout manager. You become responsible for managing the size and position of the child components, that's the point.
Updated with new example
public class TestLayeredDialog {
public static void main(String[] args) {
new TestLayeredDialog();
}
public TestLayeredDialog() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JDialog dialog = new JDialog();
dialog.setModal(true);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setLayout(new BorderLayout());
JLabel label = new JLabel("Hello new world");
label.setSize(label.getPreferredSize());
label.setLocation(0, 0);
dialog.getLayeredPane().add(label, new Integer(1));
dialog.setSize(100, 100);
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
System.exit(0);
}
});
}
}
The layered pane of the JRootPane is responsible for (amongst other things) laying out the content pane and menu bar. It is also used (in some cases) to display things like popups.
Have a read through How to Use Root Panes
You can choose to put components in the root pane's layered pane. If
you do, then you should be aware that certain depths are defined to be
used for specific functions, and you should use the depths as
intended. Otherwise, your components might not play well with the
others. Here's a diagram that shows the functional layers and their
relationship:
Using this, means you are competing with components already on the screen.
Unless you have VERY good reason to be messing with this component, I would suggest you avoid it as 1- It's possible to be changed in the future (the layer position of the components) and 2- It may interfere with other components used by the Swing API
This example seems to work with the following lines added to the constructor:
this.addMouseListener(new MouseHandler(this));
this.add(new JLabel("Label"));
this.add(new JButton(UIManager.getIcon("html.pendingImage")));

No content while using SWING + JUNG to refresh graph visualization

I have following java code in my thread class:
#Override
public void run() {
JFrame window = new JFrame("Visualization POC");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true) {
window.setVisible(false);
Layout<Node,Edge> layout = new CircleLayout<Node, Edge>(graph);
layout.setSize(new Dimension(300, 300));
BasicVisualizationServer<Node, Edge> vv = new BasicVisualizationServer<Node, Edge>(layout);
vv.setPreferredSize(new Dimension(350, 350));
vv.getRenderContext().setVertexFillPaintTransformer(new NodeColorTransformer());
vv.getRenderContext().setEdgeDrawPaintTransformer(new EdgeColorTransformer());
window.getContentPane().add(vv);
window.pack();
window.setVisible(true);
try {
Thread.sleep(ONE_SECOND);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I want to use it to refresh state of graph visualization, but I got stuck on massive problem. When the block of code creating layout and setting content of JFrame is inside while loop it is not displayed in output window. When I place it before while, it works fine but it isn't that what I want. I run this thread via SpringUtilities.invokeLater in my main class.
I can see that the window is refresh, because it is blinking for a while.
I'm looking forward for any tips.
You invoke your code from EDT thread. Any update to the component will be painted at the end of the EDT thread. Your thread will not exit
I have modified your code little, it works fine. please replace JLabel with your jung .
final JFrame window = new JFrame("Visualization POC");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final Random ran = new Random();
while (true) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
window.setVisible(false);
JPanel panel = new JPanel();
JLabel label = new JLabel();
int nextInt = ran.nextInt(100);
label.setText("Test Label"+String.valueOf(nextInt));
System.out.println(nextInt);
panel.add(label);
window.getContentPane().removeAll();
window.getContentPane().add(panel);
window.pack();
window.setVisible(true);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

How to turn on buttons once turned off in ActionListener

Problem: Code does not turn the button back on (Example gives it 5 seconds for you to press)
Example code:
public static void main(String[] args) throws InterruptedException
{
Example call = new Example();
Thread.sleep(5000);
call.ButtonSwitch(1);
}
NOTE: this is the smallest coding i could make to show my problem
public class Example extends JFrame implements ActionListener {
static Example frame2 = new Example();
GridLayout experimentLayout = new GridLayout(0,1);
JPanel Game = new JPanel();
JButton button1 = new JButton("Press");
public Example()
{
Create();
}
public void Set()
{
setResizable(false);
}
public static void Create() {
/* Use an appropriate Look and Feel */
try {
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
/* Turn off metal's use of bold fonts */
UIManager.put("swing.boldMetal", Boolean.FALSE);
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI()
{
//Create and set up the window.
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up the content pane.
frame2.addComponentsToPane(frame2.getContentPane());
//Display the window.
frame2.pack();
frame2.setVisible(true);
}
public void addComponentsToPane(final Container pane)
{
Game.setLayout(experimentLayout);
JPanel controls = new JPanel();
controls.setLayout(new GridLayout(2,3));
//Set up components preferred size
JButton b = new JButton("Just fake button");
Dimension buttonSize = b.getPreferredSize();
Game.setPreferredSize(new Dimension((int)(buttonSize.getWidth() * 2),
(int)(buttonSize.getHeight() * 1)* 4));
Game.add(button1);
button1.addActionListener(this);
//Process the Apply gaps button press
pane.add(Game, BorderLayout.NORTH);
pane.add(new JSeparator(), BorderLayout.CENTER);
pane.add(controls, BorderLayout.SOUTH);
}
//Turns button off On Click
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == button1)
{
button1.setEnabled(false);
}
}
//This does not turn the button on but tries to
public void ButtonSwitch(int num)
{
if (num == 1)
{
System.out.println("This is called");
button1.setEnabled(true);
}
}
}
I want to make the method Enable the button, but if this is not possible a way to do this in action listener without user input would be the second option (which would look like the Button switch method placed inside the ActionListener)
The problem comes from the bad design of the class. The point is that you are not calling setEnabled(true) and setEnabled(false) on the same button1. In your main,
Example call = new Example();
Thread.sleep(5000);
call.ButtonSwitch(1);
the last line invokes setEnabled(true) on the button of call, while the actionPerformed invokes the setEnabled(false) on the button of frame2.
Regardless, you are doing it wrong:
Don't mix the main (entry) thread with the EDT.
Don't hold a member of the same class type as the containing class (unless there's a special reason to do so).
Here is a real MCVE of a working code:
public class Example extends JFrame {
JButton button = new JButton("Press");
Timer timer = new Timer(5000, e -> button.setEnabled(true));
public Example() {
add(button);
button.addActionListener(e -> {
button.setEnabled(false);
timer.start();
});
timer.setRepeats(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public static void main(String[] args) throws InterruptedException {
SwingUtilities.invokeLater(() -> new Example());
}
}
Notes:
Method and non-final variable names start with a lowercase.
Don't use setPreferredSize, override getPreferredSize instead.

Categories

Resources