Thanks to a previous question answered I am now able to start my application as a tray icon (Java frame iconified issue), however I am now running into a few different issues and I am having trouble figuring out how to fix them. When the main program runs, the console window indeed no longer launches full screen as intended, however instead of just forming a system tray icon in the bottom right corner, the window also forms a traditional minimized window on the task bar. I have noticed that previously before I made this change, when the "Hide Window" button is pressed, the main taskbar window disappears leaving only the smaller system tray icon in the right corner. It seems the changes recommended in the previous question keeps the window running, but just seems to hide it from view. How can I change this behavior? I only expected to see the small system tray icon in the bottom right corner. Also, upon exiting the main application, the tray icons don't close down. They stay open, sometimes piling up if the main application is launched multiple times. If only I could figure out where the "Hide Window" action was coming from, I feel like I could figure this out, but alas, I cant see to find the actions of that button referenced anywhere in the code. Please help!
package com.skcraft.launcher.dialog;
import com.skcraft.launcher.Launcher;
import com.skcraft.launcher.swing.LinedBoxPanel;
import com.skcraft.launcher.swing.MessageLog;
import com.skcraft.launcher.swing.SwingHelper;
import com.skcraft.launcher.util.PastebinPoster;
import com.skcraft.launcher.util.SharedLocale;
import lombok.Getter;
import lombok.NonNull;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import static com.skcraft.launcher.util.SharedLocale.tr;
/**
* A frame capable of showing messages.
*/
public class ConsoleFrame extends JFrame {
private static ConsoleFrame globalFrame;
#Getter private final Image trayRunningIcon;
#Getter private final Image trayClosedIcon;
#Getter private final MessageLog messageLog;
#Getter private LinedBoxPanel buttonsPanel;
private boolean registeredGlobalLog = false;
/**
* Construct the frame.
*
* #param numLines number of lines to show at a time
* #param colorEnabled true to enable a colored console
*/
public ConsoleFrame(int numLines, boolean colorEnabled) {
this(SharedLocale.tr("console.title"), numLines, colorEnabled);
}
/**
* Construct the frame.
*
* #param title the title of the window
* #param numLines number of lines to show at a time
* #param colorEnabled true to enable a colored console
*/
public ConsoleFrame(#NonNull String title, int numLines, boolean colorEnabled) {
messageLog = new MessageLog(numLines, colorEnabled);
trayRunningIcon = SwingHelper.createImage(Launcher.class, "tray_ok.png");
trayClosedIcon = SwingHelper.createImage(Launcher.class, "tray_closed.png");
setTitle(title);
setIconImage(trayRunningIcon);
setSize(new Dimension(650, 400));
setExtendedState(JFrame.ICONIFIED); //This is the new line of code added to minimize the window on load
initComponents();
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent event) {
performClose();
}
});
}
/**
* Add components to the frame.
*/
private void initComponents() {
JButton pastebinButton = new JButton(SharedLocale.tr("console.uploadLog"));
JButton clearLogButton = new JButton(SharedLocale.tr("console.clearLog"));
buttonsPanel = new LinedBoxPanel(true);
buttonsPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
buttonsPanel.addElement(pastebinButton);
buttonsPanel.addElement(clearLogButton);
add(buttonsPanel, BorderLayout.NORTH);
add(messageLog, BorderLayout.CENTER);
clearLogButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
messageLog.clear();
}
});
pastebinButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pastebinLog();
}
});
hideMessages();
}
/**
* Register the global logger if it hasn't been registered.
*/
private void registerLoggerHandler() {
if (!registeredGlobalLog) {
getMessageLog().registerLoggerHandler();
registeredGlobalLog = true;
}
}
/**
* Attempt to perform window close.
*/
protected void performClose() {
messageLog.detachGlobalHandler();
messageLog.clear();
registeredGlobalLog = false;
dispose();
}
/**
* Send the contents of the message log to a pastebin.
*/
private void pastebinLog() {
String text = messageLog.getPastableText();
// Not really bytes!
messageLog.log(tr("console.pasteUploading", text.length()), messageLog.asHighlighted());
PastebinPoster.paste(text, new PastebinPoster.PasteCallback() {
#Override
public void handleSuccess(String url) {
messageLog.log(tr("console.pasteUploaded", url), messageLog.asHighlighted());
SwingHelper.openURL(url, messageLog);
}
#Override
public void handleError(String err) {
messageLog.log(tr("console.pasteFailed", err), messageLog.asError());
}
});
}
public static void showMessages() {
ConsoleFrame frame = globalFrame;
if (frame == null) {
frame = new ConsoleFrame(10000, false);
globalFrame = frame;
frame.setTitle(SharedLocale.tr("console.launcherConsoleTitle"));
frame.registerLoggerHandler();
frame.setVisible(true);
} else {
frame.setVisible(true);
frame.registerLoggerHandler();
frame.requestFocus();
}
}
public static void hideMessages() {
ConsoleFrame frame = globalFrame;
if (frame != null) {
frame.setVisible(false);
}
}
}
Related
Good Afternoon, I'm back with another new-bee question. I am trying to create an program with a Star Trek inspired interface. I do not want to use dialog boxes with the program.
My interface is drawn on the screen in the fraMain class that my program calls first. It is shown below:
/**
* Troy Marker Enterprises
* TMEA-002-J: PHMS Database - Java
* Main Activity Code File
* Copyright (c) 2020 By Troy Marker Enterprises
* All Rights Under Copyright Reserved
*
* The code in this file was created for use with Troy Marker Enterprises Software.
* Use of this code by the public is strictly prohibited.
*/
package com.troymarkerenterprises;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Main program frame class
*/
public class fraMain extends JFrame implements ActionListener{
/**
* Program variable definitions
*/
private JPanel panMainMenu;
public static JPanel panSubMenu;
public static JPanel panTop;
private JPanel panBottom;
private int screenWidth;
private int screenHeight;
/**
* Method to start the program
* #param args - Method arguments
*/
public static void main(String[] args) {
new fraMain();
}
/**
* Method to draw the main window
*/
public fraMain() {
EventQueue.invokeLater(this::run);
}
/**
* Draw the main window
*/
private void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
GraphicsEnvironment graphics = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = graphics.getDefaultScreenDevice();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(null);
this.setBackground(Color.BLACK);
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
screenWidth = gd.getDisplayMode().getWidth();
screenHeight = gd.getDisplayMode().getHeight();
this.panMainMenu = new ClassMainMenu(screenWidth, screenHeight);
panSubMenu = new ClassSubMenu(screenWidth, screenHeight);
panSubMenu.setVisible(false);
panTop = new ClassTopFrame(screenWidth,screenHeight);
this.panBottom = new ClassBottomFrame(screenWidth, screenHeight);
this.add(this.panMainMenu);
this.add(panSubMenu);
this.add(panTop);
this.add(panBottom);
this.pack();
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
device.setFullScreenWindow(this);
}
#Override
public void actionPerformed(ActionEvent e) {
}
}
The screen is divided into four panels: panMainMenu, panSubMenu, panTop, and panBotom.
Each panel has its own class that draw its contents.
The panSubMenu is hidden until a button in the Main Menu is pressed, which show the sub menu. That part is working fine.
However, when I click the Exit Button on the main menu the only t hing that happens is the top frame turns white.
Here is my code for the Main Menu:
package com.troymarkerenterprises;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ClassMainMenu extends JPanel implements ActionListener {
final TMButton department;
final TMButton grade;
final TMButton user;
final TMButton exit;
private String MainMenuOption;
private final int screenHeight;
private final int screenWidth;
public ClassMainMenu(int screenWidth, int screenHeight) {
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
this.setBackground(Color.BLACK);
this.setBounds(0, 0, 160, screenHeight);
department = new TMButton("DEPARTMENT", "green");
grade = new TMButton("GRADES", "green");
user = new TMButton("USERS", "green");
exit = new TMButton("EXIT","blue");
department.addActionListener(this);
grade.addActionListener(this);
user.addActionListener(this);
exit.addActionListener(this);
this.add(department);
this.add(grade);
this.add(user);
this.add(exit);
}
public void deselectAll() {
for (Component c : this.getComponents()) {
if (c instanceof TMButton) {
((TMButton)c).setSelected(false);
}
}
}
#Override
public void actionPerformed(ActionEvent e) {
ClassTopFrame topFrame = new ClassTopFrame();
if(e.getSource()==department) {
this.deselectAll();
fraMain.panSubMenu.setVisible(true);
department.setSelected(true);
MainMenuOption = "Department";
}
if(e.getSource()==grade) {
this.deselectAll();
fraMain.panSubMenu.setVisible(true);
grade.setSelected(true);
MainMenuOption = "Grade";
}
if(e.getSource()==user) {
this.deselectAll();
fraMain.panSubMenu.setVisible(true);
user.setSelected(true);
MainMenuOption = "User";
}
if(e.getSource()==exit) {
this.deselectAll();
exit.setSelected(true);
fraMain.panTop = topFrame.exitProgram(fraMain.panTop);
//System.exit(0);
}
}
}
And the code for the top panel:
package com.troymarkerenterprises;
import javax.swing.*;
import java.awt.*;
import java.util.Objects;
public class ClassTopFrame extends JPanel{
private int screenWidth;
private int screenHeight;
public ClassTopFrame(int Width, int Height) {
screenWidth = Width;
screenHeight = Height;
this.setBackground(Color.BLACK);
this.setBounds(160, 0, screenWidth-160, screenHeight/2);
JLabel jl=new JLabel();
jl.setIcon(new javax.swing.ImageIcon(Objects.requireNonNull(getClass().getResource("/i_TMEA-0002-J_Logo.png"))));
this.add(jl);
}
public ClassTopFrame() {
}
public JPanel exitProgram(JPanel returnPanel) {
returnPanel.setBackground(Color.BLACK);
returnPanel.setBounds(160, 0, screenWidth-160, screenHeight/2);
JLabel jl=new JLabel();
jl.setIcon(new javax.swing.ImageIcon(Objects.requireNonNull(getClass().getResource("/i_TMEA-0002-J_Logo.png"))));
returnPanel.add(jl);
return returnPanel;
}
}
My plan is the have a new panel replace the top panel when the Exit button is pressed. I know the current code will only display the same contents of the panel when the button is clicked, it just wanted to put something the int exitProgram method for it to display.
As I said, I am a Java new-bee. I am not even sure if what I want to do is possible, I want to think so. Can anyone help me figure this out?
Thanks, Troy
Here is a picture of what I am looking to do:
The right side of the screen will show the sub menu when one of the buttons is clicked.
ADDITION:
In response to some help I have been getting, I am trying to switch to a card layout, but am having problem. I tried posting here, but it looks like adding the required information will make this post to long. So I uploaded everything to my GitHub account. The main changes I made are in this fine: https://github.com/troy-marker/TMEA-0002-J/blob/main/src/com/troymarkerenterprises/ClassBottomFrame.java
I have recently started learning java.I want to make a game like https://sites.google.com/site/millseagles/home/Games/multiplayer/tron
I have made it in c++ once using a simple graphics lib. I have the graphics part down i plan to use small images and use http://horstmann.com/sjsu/graphics/ this basic graphics lib.I can't figure out keyboard input i want it so if you press an arrow the picture adds a small green square(I have a green.png).I can't figure out to use keyboard listeners.I get all these errors.I just need a simple lib that i can say getKey() or something and i can use if() to figure out the action.this is the code I have.I was messing with the key event but don't understand it.
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.*;
public class game implements KeyListener
{
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){}
public game()//snake like game
{
}
public void test()
{
int x=30,y=30;//middle total 60x60
tile[] map=new tile[3600];//tile is a class i made that is a picture and some int and bool using the simple lib i linked 60 by 60 tiles
for(int i=0;i<3600;i++)
{
map[i]=new tile();
}
}
public void keyPressed(KeyEvent e)//this does not work i want it to work when a key is clicked
{
while(x>0)//this part works when it is not in the keypressed function
{
map[(y*60)+x].load(4);//4 refrences a green rectangle image
map[(y*60)+x].draw(x,y,10);//draw it based on x and y 10 pixels sized tiles
x--;//make a line going left
}
}
}
I know this may be messy.I have tested my code it works it just breaks when i try to implement keyboard events.If you can point me to a much more beginner friendly lib that would be great.
You simply have to add the listener to something (e.g. the window where the game is being played).
I will give you an example, where we will simply display the code of the key being stroked.
This is the class where you produce the interface:
import java.awt.Dimension;
import javax.swing.JFrame;
public class Game {
public static void main(String[] args) {
/* Creating a window (300x400) */
JFrame frame = new JFrame("Add your own title");
frame.setPreferredSize(new Dimension(300, 400));
/* This is the part where we add the keyListener (notice that I am also sending
* this window as a parameter so that the listener can modify it)*/
frame.addKeyListener(new ArrowListener(frame));
/* Making the window visible */
frame.pack();
frame.setVisible(true);
}
}
And this is the class where we have the listener:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ArrowListener implements KeyListener {
/* We keep the window as an instance variable so we can modify it once the event is triggered */
JFrame frame;
/* This is the constructor */
public ArrowListener(JFrame j) {
frame = j;
}
/* This is where the magic happens */
public void keyPressed(KeyEvent e) {
/* Modify this with what you actually want it to do */
/* We clear the panel so we can add new text without any other text behind it */
frame.getContentPane().removeAll();
/* We add some text that actually shows the keyCode (left arrow = 37, top = 38, right = 39, bottom = 40) */
frame.add(new JLabel("Key Code #" + String.valueOf(e.getKeyCode())));
/* Redrawing the window */
frame.revalidate();
}
/* These two are part of the contract we made when we decided to
* implement the KeyListener */
public void keyTyped(KeyEvent e) { /* Do nothing */ }
public void keyReleased(KeyEvent e) { /* Do nothing */ }
}
Note: when running the program press the keys to see the text appearing on the window.
I didn't get around the library you were using, but I used the most popular one called swing (tutorial)
Can someone help me how can I include emoticons in this code.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
/**
* A simple Swing-based client for the chat server. Graphically
* it is a frame with a text field for entering messages and a
* textarea to see the whole dialog.
*
* The client follows the Chat Protocol which is as follows.
* When the server sends "SUBMITNAME" the client replies with the
* desired screen name. The server will keep sending "SUBMITNAME"
* requests as long as the client submits screen names that are
* already in use. When the server sends a line beginning
* with "NAMEACCEPTED" the client is now allowed to start
* sending the server arbitrary strings to be broadcast to all
* chatters connected to the server. When the server sends a
* line beginning with "MESSAGE " then all characters following
* this string should be displayed in its message area.
*/
public class ChatClient {
BufferedReader in;
PrintWriter out;
JFrame frame = new JFrame("Chatter");
JTextField textField = new JTextField(40);
JTextArea messageArea = new JTextArea(8, 40);
/**
* Constructs the client by laying out the GUI and registering a
* listener with the textfield so that pressing Return in the
* listener sends the textfield contents to the server. Note
* however that the textfield is initially NOT editable, and
* only becomes editable AFTER the client receives the NAMEACCEPTED
* message from the server.
*/
public ChatClient() {
// Layout GUI
textField.setEditable(false);
messageArea.setEditable(false);
frame.getContentPane().add(textField, "North");
frame.getContentPane().add(new JScrollPane(messageArea), "Center");
frame.pack();
// Add Listeners
textField.addActionListener(new ActionListener() {
/**
* Responds to pressing the enter key in the textfield by sending
* the contents of the text field to the server. Then clear
* the text area in preparation for the next message.
*/
public void actionPerformed(ActionEvent e) {
out.println(textField.getText());
textField.setText("");
}
});
}
/**
* Prompt for and return the address of the server.
*/
private String getServerAddress() {
return JOptionPane.showInputDialog(
frame,
"Enter IP Address of the Server:",
"Welcome to the Chatter",
JOptionPane.QUESTION_MESSAGE);
}
/**
* Prompt for and return the desired screen name.
*/
private String getName() {
return JOptionPane.showInputDialog(
frame,
"Choose a screen name:",
"Screen name selection",
JOptionPane.PLAIN_MESSAGE);
}
/**
* Connects to the server then enters the processing loop.
*/
private void run() throws IOException {
// Make connection and initialize streams
String serverAddress = getServerAddress();
Socket socket = new Socket(serverAddress, 9001);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Process all messages from server, according to the protocol.
while (true) {
String line = in.readLine();
if (line.startsWith("SUBMITNAME")) {
out.println(getName());
} else if (line.startsWith("NAMEACCEPTED")) {
textField.setEditable(true);
} else if (line.startsWith("MESSAGE")) {
messageArea.append(line.substring(8) + "\n");
}
}
}
/**
* Runs the client as an application with a closeable frame.
*/
public static void main(String[] args) throws Exception {
ChatClient client = new ChatClient();
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setVisible(true);
client.run();
}
}
First of all, I didn't look your code to be honest (sry about that), but what you are asking is something very simple. Have you noticed that all emoticons have a sequence of characters?
Skype Example: :* :) (y) ... and so on
When compiling the message, a simple replaceAll takes place.
String message = "Of course :)";
// in this place here you will make a loop for all your emoticons or just
// match it by regex.
message = message.replaceAll(":)", imageToAdd);
sendMessage(message);
That is basically what happens in the chat when you add an emoticon. You can use a HashMap to, where the id would be the char sequence and the value would be the path or image component of that emoticon. (It is much faster if you have several)
Didnt bashed my head in your code but what i have used in my chatbox is this:
Autoreplace smiles text with appropriate images in JEditorPane.
To support the autoreplacing we need a JEditorPane with StyledEditorKit (or extension class) to provide images in text. We just add a DocumentListener to process text insert events. After inserting we check whether the changed text contains smiles string - the ":)". If it contains we replace the smile text with an appropriate image.
The example provides only one smile support - the ":)" string but can be easy extended.
NOTE: We should surround our code with SwingUtilities.invokeLater() because we cannot change document during mutation intercepted in the listener.
The example code is below:
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.*;
import java.awt.image.BufferedImage;
import java.awt.*;
public class AutoreplaceSmiles extends JEditorPane {
static ImageIcon SMILE_IMG=createImage();
public static void main(String[] args) {
JFrame frame = new JFrame("Autoreplace :) with Smiles images example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final AutoreplaceSmiles app = new AutoreplaceSmiles();
app.setEditorKit(new StyledEditorKit());
app.initListener();
JScrollPane scroll = new JScrollPane(app);
frame.getContentPane().add(scroll);
frame.setSize(400, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public AutoreplaceSmiles() {
super();
}
private void initListener() {
getDocument().addDocumentListener(new DocumentListener(){
public void insertUpdate(DocumentEvent event) {
final DocumentEvent e=event;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (e.getDocument() instanceof StyledDocument) {
try {
StyledDocument doc=(StyledDocument)e.getDocument();
int start= Utilities.getRowStart(AutoreplaceSmiles.this,Math.max(0,e.getOffset()-1));
int end=Utilities.getWordStart(AutoreplaceSmiles.this,e.getOffset()+e.getLength());
String text=doc.getText(start, end-start);
int i=text.indexOf(":)");
while(i>=0) {
final SimpleAttributeSet attrs=new SimpleAttributeSet(
doc.getCharacterElement(start+i).getAttributes());
if (StyleConstants.getIcon(attrs)==null) {
StyleConstants.setIcon(attrs, SMILE_IMG);
doc.remove(start+i, 2);
doc.insertString(start+i,":)", attrs);
}
i=text.indexOf(":)", i+2);
}
} catch (BadLocationException e1) {
e1.printStackTrace();
}
}
}
});
}
public void removeUpdate(DocumentEvent e) {
}
public void changedUpdate(DocumentEvent e) {
}
});
}
static ImageIcon createImage() {
BufferedImage res=new BufferedImage(17, 17, BufferedImage.TYPE_INT_ARGB);
Graphics g=res.getGraphics();
((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.yellow);
g.fillOval(0,0,16,16);
g.setColor(Color.black);
g.drawOval(0,0,16,16);
g.drawLine(4,5, 6,5);
g.drawLine(4,6, 6,6);
g.drawLine(11,5, 9,5);
g.drawLine(11,6, 9,6);
g.drawLine(4,10, 8,12);
g.drawLine(8,12, 12,10);
g.dispose();
return new ImageIcon(res);
}
}
I'm trying to add links into a project that i'm making in eclipse. I have researched on how to do it, but i can't find much on it that pertains to eclipse.
This is the code that im trying to add links too:
Object[] possibilities = {"" +
"AWS Welder Certification Testing",
"Computer science",
"Aviation", "Construction",
"Health science",
"Programming",
"3D design",
"Cyber security",
"Advanced Safety Certification",
"Healthcare Provider CPR",
"Dietary Manager",
"Insurance",
"Emergency 911 Operator",
"Job Safety Analysis",
"Real Estate",
"Pharmacy Technician",
"Special Needs Education",
"School Bus Driver Training",
"Phlebotomy Technician",
"Security Guard",
"Home Inspection",
"Court Reporter",
"Long Term Care/Nurse Aide (CNA)",
"EPA Lead Safe Renovator Certification",};
Component frame = null;
Icon icon = null;
String s = (String)JOptionPane.showInputDialog(
frame,
"What class might you want to attend?\n"
+ "\"The options are endless!\"",
"Class Options",
JOptionPane.PLAIN_MESSAGE,
icon,
possibilities,
"all");
When I run the program, a dialog box appears, and it gives all the options of classes above. How would I make it to where when the user clicks on a class it will link them to the website for that class?
I recommend using a JTextField rather than a JButton for this use.
E.G.
That is how it appears when the mouse is hovering over the first link.
LinkLabel.java
/* License - LGPL
LinkLabel Using the Desktop Class
There are a lot of link labels. This one uses the Java 1.6+
Desktop class for its functionality, and is thereby suitable
for applets, applications launched using JWS, and 'standard'
(non-JWS) desktop applications.
*/
import java.awt.Desktop;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.JTextField;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import javax.swing.border.MatteBorder;
import javax.swing.border.Border;
import java.net.URI;
import java.io.File;
/**
A Java 1.6+ LinkLabel that uses the Desktop class for opening
the document of interest.
The Desktop.browse(URI) method can be invoked from applications,
applets and apps. launched using Java Webstart. In the latter
two cases, the usual fall-back methods are used for sandboxed apps
(see the JavaDocs for further details).
While called a 'label', this class actually extends JTextField,
to easily allow the component to become focusable using keyboard
navigation.
To successfully browse to a URI for a local File, the file name
must be constructed using a canonical path.
#author Andrew Thompson
#version 2008/08/23
*/
public class LinkLabel
// we extend a JTextField, to get a focusable component
extends JTextField
implements MouseListener, FocusListener, ActionListener {
/** The target or href of this link. */
private URI target;
public Color standardColor = new Color(0,0,255);
public Color hoverColor = new Color(255,0,0);
public Color activeColor = new Color(128,0,128);
public Color transparent = new Color(0,0,0,0);
public boolean underlineVisible = true;
private Border activeBorder;
private Border hoverBorder;
private Border standardBorder;
/** Construct a LinkLabel that points to the given target.
The URI will be used as the link text.*/
public LinkLabel(URI target) {
this( target, target.toString() );
}
/** Construct a LinkLabel that points to the given target,
and displays the text to the user. */
public LinkLabel(URI target, String text) {
super(text);
this.target = target;
}
/* Set the active color for this link (default is purple). */
public void setActiveColor(Color active) {
activeColor = active;
}
/* Set the hover/focused color for this link (default is red). */
public void setHoverColor(Color hover) {
hoverColor = hover;
}
/* Set the standard (non-focused, non-active) color for this
link (default is blue). */
public void setStandardColor(Color standard) {
standardColor = standard;
}
/** Determines whether the */
public void setUnderlineVisible(boolean underlineVisible) {
this.underlineVisible = underlineVisible;
}
/* Add the listeners, configure the field to look and act
like a link. */
public void init() {
this.addMouseListener(this);
this.addFocusListener(this);
this.addActionListener(this);
setToolTipText(target.toString());
if (underlineVisible) {
activeBorder = new MatteBorder(0,0,1,0,activeColor);
hoverBorder = new MatteBorder(0,0,1,0,hoverColor);
standardBorder = new MatteBorder(0,0,1,0,transparent);
} else {
activeBorder = new MatteBorder(0,0,0,0,activeColor);
hoverBorder = new MatteBorder(0,0,0,0,hoverColor);
standardBorder = new MatteBorder(0,0,0,0,transparent);
}
// make it appear like a label/link
setEditable(false);
setForeground(standardColor);
setBorder(standardBorder);
setCursor( new Cursor(Cursor.HAND_CURSOR) );
}
/** Browse to the target URI using the Desktop.browse(URI)
method. For visual indication, change to the active color
at method start, and return to the standard color once complete.
This is usually so fast that the active color does not appear,
but it will take longer if there is a problem finding/loading
the browser or URI (e.g. for a File). */
public void browse() {
setForeground(activeColor);
setBorder(activeBorder);
try {
Desktop.getDesktop().browse(target);
} catch(Exception e) {
e.printStackTrace();
}
setForeground(standardColor);
setBorder(standardBorder);
}
/** Browse to the target. */
public void actionPerformed(ActionEvent ae) {
browse();
}
/** Browse to the target. */
public void mouseClicked(MouseEvent me) {
browse();
}
/** Set the color to the hover color. */
public void mouseEntered(MouseEvent me) {
setForeground(hoverColor);
setBorder(hoverBorder);
}
/** Set the color to the standard color. */
public void mouseExited(MouseEvent me) {
setForeground(standardColor);
setBorder(standardBorder);
}
public void mouseReleased(MouseEvent me) {}
public void mousePressed(MouseEvent me) {}
/** Set the color to the standard color. */
public void focusLost(FocusEvent fe) {
setForeground(standardColor);
setBorder(standardBorder);
}
/** Set the color to the hover color. */
public void focusGained(FocusEvent fe) {
setForeground(hoverColor);
setBorder(hoverBorder);
}
public static void main(String[] args) throws Exception {
JPanel p = new JPanel(new GridLayout(0,1));
File f = new File(".","LinkLabel.java");
/* Filename must be constructed with a canonical path in
order to successfully use Desktop.browse(URI)! */
f = new File(f.getCanonicalPath());
URI uriFile = f.toURI();
LinkLabel linkLabelFile = new LinkLabel(uriFile);
linkLabelFile.init();
p.add(linkLabelFile);
LinkLabel linkLabelWeb = new LinkLabel(
new URI("http://pscode.org/sscce.html"),
"SSCCE");
linkLabelWeb.setStandardColor(new Color(0,128,0));
linkLabelWeb.setHoverColor(new Color(222,128,0));
linkLabelWeb.init();
/* This shows a quirk of the LinkLabel class, the
size of the text field needs to be constrained to
get the underline to appear properly. */
p.add(linkLabelWeb);
LinkLabel linkLabelConstrain = new LinkLabel(
new URI("http://sdnshare.sun.com/"),
"SDN Share");
linkLabelConstrain.init();
/* ..and this shows one way to constrain the size
(appropriate for this layout).
Similar tricks can be used to ensure the underline does
not drop too far *below* the link (think BorderLayout
NORTH/SOUTH).
The same technique can also be nested further to produce
a NORTH+EAST packing (for example). */
JPanel labelConstrain = new JPanel(new BorderLayout());
labelConstrain.add( linkLabelConstrain, BorderLayout.EAST );
p.add(labelConstrain);
LinkLabel linkLabelNoUnderline = new LinkLabel(
new URI("http://java.net/"),
"java.net");
// another way to deal with the underline is to remove it
linkLabelNoUnderline.setUnderlineVisible(false);
// we can use the methods inherited from JTextField
linkLabelNoUnderline.
setHorizontalAlignment(JTextField.CENTER);
linkLabelNoUnderline.init();
p.add(linkLabelNoUnderline);
JOptionPane.showMessageDialog( null, p );
}
}
That when painted for the first time, it is not painted correctly.
However, when I minimize the frame and restore it, it is painted correctly.
How will I fix this? I have tried repaint().
Here is the code
import javax.swing.JComponent;
import javax.swing.JFrame;
import com.sun.jna.Function;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.HRESULT;
/**
* #author ex0b1t
*
*/
public class Aero {
public void enableAeroEffect(JFrame frame) {
NativeLibrary dwmapi = NativeLibrary.getInstance("dwmapi");
HWND aeroFrameHWND = new HWND(Native.getWindowPointer(frame));
MARGINS margins = new MARGINS();
margins.cxLeftWidth = -1;
margins.cxRightWidth = -1;
margins.cyBottomHeight = -1;
margins.cyTopHeight = -1;
Function extendFrameIntoClientArea = dwmapi
.getFunction("DwmExtendFrameIntoClientArea");
HRESULT result = (HRESULT) extendFrameIntoClientArea.invoke(
HRESULT.class, new Object[] { aeroFrameHWND, margins });
if (result.intValue() != 0)
System.err.println("Call to DwmExtendFrameIntoClientArea failed.");
frame.getRootPane().setDoubleBuffered(false);
frame.getRootPane().setOpaque(false);
if (frame.getRootPane().getContentPane() instanceof JComponent) {
JComponent content = (JComponent) frame.getRootPane().getContentPane();
content.setOpaque(false);
content.setDoubleBuffered(false);
}
}
/**
* #author ex0b1t
*
*/
public class MARGINS extends Structure implements Structure.ByReference {
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}
}
import javax.swing.JFrame;
/**
* #author ex0b1t
*
*/
public class MediaManager extends JFrame {
private static final long serialVersionUID = -8440221168382362270L;
public MediaManager() {
setTitle("Media Manager");
setSize(800, 600);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
/**
* #param args
*/
public static void main(String[]args){
MediaManager mediamanager = new MediaManager();
mediamanager.setVisible(true);
new Aero().enableAeroEffect(mediamanager);
mediamanager.repaint();
}
}
Thank in advance.
What do you mean when you say it is not correctly painted?
I had a similar problem where when my frame was painted for the first time the contentPane was totally black. When i minimized the frame and then maximizing it,it was painted correctly (but not always- there were times i had to do it 2 or 3 times.) It turned out it was the drivers of my graphics card. I reinstalled them and it worked fine! (I had a Randeon)
also try
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
mediamanager.setVisible(true);
new Aero().enableAeroEffect(mediamanager);
mediamanager.repaint();
}
}
Threads and Swing
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html
SwingUtilities.invokeLater
setting the extended state of the frame to iconified and back to normal will paint the frame correctley. however when i add a component to the frame the backround is regrawn incorectley.
frame.setExtendedState(JFrame.ICONIFIED);
frame.setExtendedState(JFrame.NORMAL);