Swing: How to set Custom Cursor as transparent? - java

I'm changing a cursor, using a PNG image (with transparency), but when I run the code below, the image doesn't look like it should.
public void CustomCursor()
{
Toolkit t1 = Toolkit.getDefaultToolkit();
Image img = t1.getImage("src/AppImages/Cursor1.png");
Point point = new Point(0,0);
Cursor cursor = t1.createCustomCursor(img, point, "Cursor");
setCursor(cursor);
}
This method is called in the Jframe's constructor.
This is the cursor1.png image, sized 25x25px.
After running the code:
If I use cursor1.png as a JLabel, it looks OK:
MCVE
import java.awt.*;
import java.net.*;
import java.util.logging.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class CustomCursor {
private JComponent ui = null;
CustomCursor() {
initUI();
}
public void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(20, 200, 20, 200));
Toolkit t1 = Toolkit.getDefaultToolkit();
Image img;
try {
URL url = new URL("http://i.stack.imgur.com/sJKuE.png");
img = t1.getImage(url);
Point point = new Point(0, 0);
Cursor cursor = t1.createCustomCursor(img, point, "Cursor");
ui.setCursor(cursor);
ui.add(new JLabel(new ImageIcon(url)));
} catch (MalformedURLException ex) {
Logger.getLogger(CustomCursor.class.getName()).log(Level.SEVERE, null, ex);
}
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
CustomCursor o = new CustomCursor();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
Can anyone tell why that happens?

The issue is Windows; transparent pixels just aren't taken into account.
There is a really good answer on how to fix this on this post.
Another good answer here.

Related

Java Change JButton Color with Method

I've implemented a JFrame with 25 JButton components to represent the available rooms in a hotel. I do know this is not the whole program but how can I create a method in which when pressed the color changes?
The colors for available rooms is green and I would like to change them to red.
This code uses a JToggleButton with different colored icons for standard & selected states. A JCheckBox might also be used.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.*;
import java.util.*;
public class RoomReservationToggle {
private JComponent ui = null;
private String reservedPath = "https://i.stack.imgur.com/xj49g.png";
private String freePath = "https://i.stack.imgur.com/zJ8am.png";
RoomReservationToggle() {
try {
initUI();
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
}
public void initUI() throws MalformedURLException {
if (ui != null) {
return;
}
ui = new JPanel(new GridLayout(0, 4, 4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
ImageIcon reservedIcon = new ImageIcon(new URL(reservedPath));
ImageIcon freeIcon = new ImageIcon(new URL(freePath));
Random r = new Random();
for (int ii = 1; ii < 17; ii++) {
// a JCheckBox might also be used
JToggleButton tb = new JToggleButton(freeIcon, r.nextBoolean());
tb.setSelectedIcon(reservedIcon);
ui.add(tb);
}
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
RoomReservationToggle o = new RoomReservationToggle();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
You can use the methods setForeground() and setBackground() to change colours.
Make sure you call these methods from the event thread/queue.
Your configured L&F can ignore these however. Sometimes calling setOpaque(true) might help in those cases.

Display troubles with canvas

Currently I am trying to have a JFrame which holds two JPanel components - the first JPanel component is meant to hold the various buttons that a user can click to interact with the program & draw images to the screen. The second, and this is where the trouble begins, holds the actual Canvas object to which I am trying to draw to.
The problem I am having is the second panel is not actually being drawn to. I've tried a variety of other approaches and checks, but everything suggests the current code should work.
As a test, I am simply trying to do a fillRect() onto the drawing panel, but to no avail. Here is my code:
//Creating the components & JFrame:
public static void createDisplay() {
JFrame f = new JFrame();//When JFrame flowlayout manager removed, the rectangle was drawn.
c = new Canvas();
width = 500;
height = 500;
f.setLayout(new FlowLayout());
f.add(addButtons()); //private method that covers the button panel
JPanel drawPanel = new JPanel();
drawPanel.add(c);
c.setFocusable(false);
f.add(drawPanel);
f.setPreferredSize(new Dimension(height, width));
lstnr = new Listeners();
f.addKeyListener(lstnr);
f.addMouseListener(lstnr);
f.addMouseMotionListener(lstnr);
f.setLocationRelativeTo(null);
f.pack();
f.setVisible(true);
}
And the code that does the actual drawing to the screen:
private void render() {
bs = c.getBufferStrategy();
if(bs == null) {
c.createBufferStrategy(3);
return;
}
do {
do {
g = bs.getDrawGraphics();
l.setGraphicsObj(g);
g.clearRect(0, 0, width, height);
for(Symbols s : l.getSymbolsArray());
s.renderSymbols();
}
g.fillRect(0, 0, 50, 50); //Just to test & make sure it works
g.dispose();
}while(bs.contentsRestored());
bs.show();
}while(bs.contentsLost());
}
Now I'd like to stress again that the rectangle was drawn when I removed the f.setLayoutManager(new FlowLayout()); snippet from the createDisplay() method. Any help is much appreciated.
You have conflicting painting systems. The one been used to paint the BufferStrategy and the one been used by Swing to paint it's components
Mixing heavy and light weight components is problematic at the best of times, you should do everything you can to reduce the overlap
A Canvas has a default preferred size of 0x0, which is what the FlowLayout will use to determine how best it should be laid out
A "possible" solution might be to focus on placing the Canvas within it's own spot and seperate the Swing elements.
You're still running into a world of trouble, as you will need to manage the data between two distinct thread contexts
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.image.BufferStrategy;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
PaintPane paintPane = new PaintPane();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ButtonPane(), BorderLayout.WEST);
frame.add(paintPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
paintPane.start();
}
});
}
public class ButtonPane extends JPanel {
public ButtonPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
for (int index =0; index < 5; index++) {
add(new JButton(Integer.toString(index)), gbc);
}
}
}
public class PaintPane extends Canvas {
private Thread renderThread;
private AtomicBoolean running = new AtomicBoolean(true);
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void start() {
if (renderThread != null) {
return;
}
running.set(true);
renderThread = new Thread(new Runnable() {
#Override
public void run() {
while (running.get()) {
render();
try {
Thread.sleep(5);
} catch (InterruptedException ex) {
}
}
}
});
renderThread.start();
}
public void stop() {
if (renderThread != null) {
return;
}
running.set(false);
renderThread.interrupt();
try {
renderThread.join();
} catch (InterruptedException ex) {
}
renderThread = null;
}
protected void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
do {
do {
Graphics g = bs.getDrawGraphics();
// :/
//l.setGraphicsObj(g);
g.clearRect(0, 0, getWidth(), getHeight());
//for (Symbols s : l.getSymbolsArray()) {
// // This is where g should be passed
// s.renderSymbols();
//}
g.setColor(Color.BLUE);
g.fillRect(0, 0, 50, 50); //Just to test & make sure it works
g.dispose();
} while (bs.contentsRestored());
bs.show();
} while (bs.contentsLost());
}
}
}

Java JComboBox scroll to selected item

I have a grid with data and a JComboBox with a lot of users in it, of which one is selected. I would like to scroll to the selected item to the area where user can't see the rest of the data(the bottom of the grid) so that my JScrollPane will jump to this area automatically.
How can I do that?
I think this has something to do with scrollRectToVisible() method.
A JComboBox needs no JScrollPane.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class OneLineCombo {
private JComponent ui = null;
OneLineCombo() {
initUI();
}
public void initUI() {
if (ui!=null) return;
ui = new JPanel(new BorderLayout(4,4));
ui.setBorder(new EmptyBorder(4,20,4,20));
String[] fontFamily = GraphicsEnvironment.
getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
JComboBox fontCombo = new JComboBox(fontFamily);
fontCombo.setMaximumRowCount(1);
ui.add(fontCombo, BorderLayout.PAGE_START);
ui.add(new JLabel("Type some letters of the font name to select it"),
BorderLayout.PAGE_END);
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
OneLineCombo o = new OneLineCombo();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}

How do I add more buttons in a menu of this type (there's a pic showing the type of menu)?

I don't know the name of this type of menu, but I want to add an item to this kind of menu.
Follow the link for an example of the menu: Link: http://postimg.org/image/7izr3zapl/full/
IntelliJ IDEA has implemented this for Windows and OS X, so you could use it as an example.
Focusing on Windows here, you can take a look at the
RecentTasks class for the implementation. To add the recent tasks, the addTasksNativeForCategory native method gets called. This C++ method is implemented in the following file: jumplistbridge.cpp.
Those are menu items with icons. They are not buttons!
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.URL;
import javax.imageio.ImageIO;
public class MenuWithIcon {
private JComponent ui = null;
String[] urlStrings = {
"http://i.stack.imgur.com/gJmeJ.png",
"http://i.stack.imgur.com/gYxHm.png",
"http://i.stack.imgur.com/F0JHK.png"
};
String[] menuNames = {
"Blue Circle", "Green Triangle", "Red Square"
};
MenuWithIcon() {
initUI();
}
public void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
Image img = new BufferedImage(300, 150, BufferedImage.TYPE_INT_ARGB);
ui.add(new JLabel(new ImageIcon(img)));
}
public JMenuBar getMenuBar() throws Exception {
JMenuBar mb = new JMenuBar();
JMenu menu = new JMenu("Menu");
mb.add(menu);
for (int i=0; i<urlStrings.length; i++) {
URL url = new URL(urlStrings[i]);
Image img = ImageIO.read(url);
JMenuItem mi = new JMenuItem(menuNames[i], new ImageIcon(img));
menu.add(mi);
}
return mb;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
MenuWithIcon o = new MenuWithIcon();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
try {
f.setJMenuBar(o.getMenuBar());
} catch (Exception ex) {
ex.printStackTrace();
}
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}

Creating GUI with using border layout Swing

I'm trying to create a GUI with java. My gui will be simple. You can see what I want from here : http://sketchtoy.com/64839370
In order to do that, I have decided to use BorderLayout as suggested on the web. I have two Jpanel object and I have put them into jFrame whose layout is borderlayout. You can see my simplified code below :
private Display display= new Display(); // Display extends JPanel
public Simulation()
{
super();
// frame settings
setTitle("Label of JFrame ");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBounds(100,100,1094,560);
contentPane=this.getContentPane();
setResizable(false);
contentPane.setLayout(new BorderLayout());
try {
LeftPanelLogo=ImageIO.read(new File("logo.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// generate left panel (information panel)
leftPanel=new JPanel(){
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d=(Graphics2D)g;
g2d.drawImage(LeftPanelLogo, 10, 250, null);
}
};
//leftPanel.setLayout(null);
// add panels to contentPane
leftPanel.setBackground(Color.WHITE);
display.setBackground(Color.BLACK);
contentPane.add(leftPanel,BorderLayout.WEST);
contentPane.add(display,BorderLayout.CENTER);
}
In Display class constructor I have only the following code:
try
{
bgPicture = ImageIO.read(new File("bg.jpg"));
}
catch (IOException e)
{
e.printStackTrace();
}
When I run the code, I saw that almost all the screen is fulfilled with the panel which is on the center, and I could not see the leftPanel, (in other words, all screen was black since I set the background of display panel to black)
So, how could I fix it ?
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class LogoLayout {
private JComponent ui = null;
LogoLayout() {
initUI();
}
public void initUI() {
if (ui!=null) return;
ui = new JPanel(new BorderLayout(4,4));
ui.setBorder(new EmptyBorder(4,4,4,4));
BufferedImage logo = new BufferedImage(
276,560,BufferedImage.TYPE_INT_RGB);
/* All that's needed */
ui.add(new JLabel(new ImageIcon(logo)), BorderLayout.LINE_START);
ui.add(new JTextArea("Display", 3, 44));
/* All that's needed */
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
LogoLayout o = new LogoLayout();
JFrame f = new JFrame("Logo Layout");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}

Categories