I want to block input to a window, but still be able to move it.
If there was a modal dialog type allowing the window that spawned it to move, then I would be happy.
Say I have a window that opens another window. This second window then opens a modal dialog, which blocks input to the other two windows (fine), but also locks these two windows in place (why - Amigas didn't do this :) ?).
My problem is that I may need to visually read something in the first window for use in the dialog, but this may not be possible because the second window is locked in place, covering it.
I have almost solved this with glass panes, I think. I set the class below to be the glass pane of the root pane of my window, then I call setVisible(true) on it when I want to block and setVisible(false) when I want to unlock the window. When locked, the window greys out to indicate this.
Mouse input is blocked except for closing the window which is fine for now - the problem is that I can still tab around the components on the blocked window and if I get to an editable one, I can edit it with the keyboard, regardless of my empty KeyListener.
Is there an easy way I can prevent the components behind the glass pane from gaining focus?
I am hoping it can be done on the "InputSink" class itself.
I have tried adding its own selfish focus traversal policy and requesting focus when it is visible, but this has no effect.
I have also tried an example I found where a FocusListener was added, whose focusLost method requests focus if the glass pane is visible, but that is overkill, as the window then always stays at front.
Does anybody know a solution in between those two extremes? This is what I have:
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.FocusTraversalPolicy;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.MouseAdapter;
import javax.swing.JPanel;
public class InputSink extends JPanel {
public InputSink() {
this(0.2f); //Default opacity.
}
public InputSink(float alpha) {
setOpaque(false);
setBackground(new Color(0, 0, 0, alpha)); //Just store it here.
addMouseListener(new MouseAdapter() {});
addKeyListener(new KeyAdapter() {});
setFocusTraversalPolicy(new FocusTraversalPolicy() {
#Override
public Component getLastComponent(Container aContainer) {
return InputSink.this;
}
#Override
public Component getFirstComponent(Container aContainer) {
return InputSink.this;
}
#Override
public Component getDefaultComponent(Container aContainer) {
return InputSink.this;
}
#Override
public Component getComponentBefore(Container aContainer, Component aComponent) {
return InputSink.this;
}
#Override
public Component getComponentAfter(Container aContainer, Component aComponent) {
return InputSink.this;
}
});
}
public void paintComponent(final Graphics gfx) { //Handle grey-out.
gfx.setColor(getBackground());
Rectangle rect = gfx.getClipBounds();
gfx.fillRect(rect.x, rect.y, rect.width, rect.height);
}
#Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible)
requestFocus();
}
}
So the version I used following Guillaume Polet's suggestion was
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class InputSink extends JPanel {
KeyEventDispatcher blockingDispatcher = new KeyEventDispatcher() {
#Override
public boolean dispatchKeyEvent(KeyEvent e) {
return InputSink.this == ((JFrame) SwingUtilities.getWindowAncestor((Component) e.getSource())).getGlassPane(); //Consume!
}
};
public InputSink) {
this(0.2f); //Default opacity.
}
public InputSinkfloat alpha) {
setOpaque(false);
setBackground(new Color(0, 0, 0, alpha)); //Just store it here.
addMouseListener(new MouseAdapter() {});
addKeyListener(new KeyAdapter() {});
}
public void paintComponent(final Graphics gfx) { //Handle grey-out.
gfx.setColor(getBackground());
Rectangle rect = gfx.getClipBounds();
gfx.fillRect(rect.x, rect.y, rect.width, rect.height);
}
#Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible)
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(blockingDispatcher);
else
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(blockingDispatcher);
}
}
Thank you!
You can add a KeyEventDispatcher to the KeyboardFocusManager to block keyboard input.
Small demo below:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class TestGlassPane {
private static final int COUNTDOWN = 10;
private static final String CLICK_ME = "Click me";
private static final Color GRAY = new Color(192, 192, 192, 128);
private JFrame frame;
private JButton button;
private Timer timer;
private int countdown;
private KeyEventDispatcher blockingDispatcher;
private static class GrayPanel extends JComponent {
#Override
protected void paintComponent(Graphics g) {
g.setColor(GRAY);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
public TestGlassPane() {
blockingDispatcher = new KeyEventDispatcher() {
#Override
public boolean dispatchKeyEvent(KeyEvent e) {
return true;
}
};
}
protected void initUI() {
frame = new JFrame(TestGlassPane.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button = new JButton(CLICK_ME);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
blockUserInput();
}
});
GrayPanel glassPane = new GrayPanel();
glassPane.addMouseListener(new MouseAdapter() {
});
frame.setGlassPane(glassPane);
frame.add(button);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
protected void blockUserInput() {
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(blockingDispatcher);
frame.getGlassPane().setVisible(true);
countdown = COUNTDOWN;
timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
countdown--;
if (countdown == 0) {
timer.stop();
frame.getGlassPane().setVisible(false);
button.setText(CLICK_ME);
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(blockingDispatcher);
} else {
button.setText("We will be back in " + countdown + " seconds");
}
}
});
timer.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestGlassPane().initUI();
}
});
}
}
Normally, the button can be activated with the Space key, but you will see that it actually gets blocked.
because the second window is locked in place
the JDialog has always been 'moveable' for me (using windows).
another possibility to block input:
when you show your non-modal dialog, include this line
frame.setEnabled(false);
also add a windowListener to the dialog, so that on closing
frame.setEnabled(true);
seems to work OK on windows, other platforms unknown
Related
Take the example from Oracle, there are some examples in your documentation.
My idea is the following:
I have achieved that my application has a transparent background, but the minimize and close application buttons do not appear
This is my code:
main
import javax.swing.JFrame;
import java.awt.*;
import javax.swing.*;
import static java.awt.GraphicsDevice.WindowTranslucency.*;
public class Textmovie extends JFrame {
/*
public Textmovie() {
//setLayout(new GridBagLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
*/
public static void main(String[] args) {
JFrame jf = new JFrame("");
jf.setUndecorated(true);
jf.setBackground(new Color(0,0,0,10));
//jf.setOpacity(0.55f);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(new texscroll());
jf.setSize(720,480);
jf.setVisible(true);
}
}
Part 2
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
/**
*
* #author inide
*/
public class texscroll extends JPanel {
int x =510 , y = 25;
public texscroll() {
setOpaque(false);
}
#Override
public void paint(Graphics g){
super.paint(g);
Graphics2D g2 = (Graphics2D)g;
Font font = new Font("Arial",Font.BOLD + Font.PLAIN,15);
g2.setFont(font);
g2.setColor(Color.BLACK);
String string = "stackoverflow stackoverflow stackoverflow stackoverflow";
g2.drawString(string ,x,y);
try{Thread.sleep(14);}
catch(Exception ex)
{
};
x-=1;
if(x==-10*string.length()){
x= 510;
}
repaint();
// System.out.println(string.length() );
}
}
And this is shown when running in NetBeans IDE 8.0.2
They can explain to me what I have to do to make the buttons appear (minimize and close application).
If you actually dig into the code based on the exception:
Exception in thread "AWT-EventQueue-0" java.awt.IllegalComponentStateException: The frame is decorated
at java.desktop/java.awt.Frame.setBackground(Frame.java:989)
You'll find that it's impossible to make a frame transparent AND be decorated...
#Override
public void setBackground(Color bgColor) {
synchronized (getTreeLock()) {
if ((bgColor != null) && (bgColor.getAlpha() < 255) && !isUndecorated()) {
throw new IllegalComponentStateException("The frame is decorated");
}
super.setBackground(bgColor);
}
}
The fact that the tutorials show it working is irrelevant and an error on the part of the tutorials.
It "might" have been possible in earlier "unreleased" versions of the API (using AWTUtilities), but it simply no longer possible
Now, we've got that out the way, this, inside paint...
try {
Thread.sleep(14);
} catch (Exception ex) {
};
x -= 1;
if (x == -10 * string.length()) {
x = 510;
}
repaint();
is not how you do animation in Swing
This is just going to cause you no end of issues, as nothing is committed to the native peer until AFTER the paintComponent exist (this is how double buffering works)
See Concurrency in Swing for more details.
A more appropriate solution might look something like...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Textmovie extends JFrame {
public static void main(String[] args) {
new Textmovie();
}
public Textmovie() throws HeadlessException {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame jf = new JFrame("");
jf.setUndecorated(true);
jf.setBackground(new Color(0, 0, 0, 10));
//jf.setOpacity(0.55f);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(new texscroll());
jf.pack();
jf.setLocationRelativeTo(null);
jf.setVisible(true);
}
});
}
public static class texscroll extends JPanel {
private int x = 510, y = 25;
private String string = "stackoverflow stackoverflow stackoverflow stackoverflow";
public texscroll() {
Font font = new Font("Arial", Font.BOLD + Font.PLAIN, 15);
setFont(font);
setForeground(Color.BLACK);
setOpaque(false);
Timer timer = new Timer(14, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
x -= 1;
if (x == -10 * string.length()) {
x = 510;
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(720, 480);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
Graphics2D g2 = (Graphics2D) g;
g2.drawString(string, x, y);
}
}
}
See How to Use Swing Timers for more details
jf.setUndecorated(true);
makes the title bar invisible and that includes the minimize and close buttons so you should remove that line (because it's false by default)
It’s because you’re calling jf.setUndecorated(true). This method removes the the title bar, which contains the minimize and maximize buttons.
Unfortunately, the window have to be undecorated to have a system title bar, but the look and feel can provide a title bar. To enable it, you have to call this before your frame is made visible:
JFrame.setDefaultLookAndFeelDecorated(true);
Using LayerUI to add labels to the upper corner of a tabbed pane. Would like to allow these labels to display as hyperlinks, so I set the color blue, the cursor to a hand and I added a mouselistener.
Howev,er when I paint the component the cursor customization and mouse listener are not not working.
sample image
Sample Application:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JLayer;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.plaf.LayerUI;
public class TopRightCornerLabelLayerUITest {
public static JPanel makeUI() {
JPanel resultPanel = new JPanel();
resultPanel.setLayout( new BorderLayout());
resultPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.add("Tab 1", new JPanel());
tabbedPane.add("Tab 2", new JPanel());
resultPanel.add(new JLayer<JComponent>(tabbedPane, new TopRightCornerLabelLayerUI()), BorderLayout.CENTER);
return resultPanel;
}
private static void initandShow()
{
JDialog dialog = new JDialog();
dialog.getContentPane().add(makeUI());
dialog.setSize(520, 240);
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
initandShow();
}
});
}
}
class TopRightCornerLabelLayerUI extends LayerUI<JComponent> {
private JPanel rubberStamp = new JPanel();
#Override public void paint(Graphics g, JComponent c) {
super.paint(g, c);
JLabel layoutHyperlink = new JLabel("<html><a href=''>File Layout and Descriptions</a></html>");
JLabel templateHyperlink = new JLabel("<html><a href=''>Download Template</a></html>");
layoutHyperlink.setForeground(Color.BLUE.darker());
layoutHyperlink.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
layoutHyperlink.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
// the user clicks on the label
System.err.println("clicked");
}
});
templateHyperlink.setForeground(Color.BLUE.darker());
templateHyperlink.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
templateHyperlink.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
// the user clicks on the label
System.err.println("clicked");
}
});
// Add components
Dimension templateDimension = templateHyperlink.getPreferredSize();
int x = c.getWidth() - templateDimension.width - 5;
SwingUtilities.paintComponent(g, templateHyperlink, rubberStamp, x, 2, templateDimension.width , templateDimension.height);
Dimension layoutDimension = layoutHyperlink.getPreferredSize();
x = c.getWidth() - layoutDimension.width - 15 - templateDimension.width;
SwingUtilities.paintComponent(g, layoutHyperlink, rubberStamp, x, 2, layoutDimension.width, templateDimension.height);
}
}
I was actually unaware of class JLayer until I read your question. I don't have a complete answer but I think it's enough to give you a push in the right direction. I was helped by the lesson in Oracle's Java tutorial: How to Decorate Components with the JLayer Class. That lesson has a section entitled Responding to Events which helped me to figure out how to partially solve your issue. Basically you are just painting the labels and not actually adding them as components and therefore they will not respond to mouse events. Since the labels can be considered part of the JLayer component that is added as a component, you can configure that JLayer to respond to mouse events. As stated in the tutorial lesson, you need to override some other methods in your TopRightCornerLabelLayerUI class. The code below contains two of those methods. Add them to your code and see if they give you the expected result.
public void installUI(JComponent c) {
super.installUI(c);
((JLayer<?>) c).setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK);
}
protected void processMouseEvent(MouseEvent e, JLayer l) {
if (e.getID() == MouseEvent.MOUSE_CLICKED) {
Point pt = e.getPoint();
if (pt.x >= xTemplateHyperlink && pt.x <= (xTemplateHyperlink + widthTemplateHyperlink)) {
System.out.println("clicked");
}
}
}
EDIT:
Forgot to mention that I added the following members to your TopRightCornerLabelLayerUI class...
private int xTemplateHyperlink;
private int yTemplateHyperlink;
private int widthTemplateHyperlink;
private int heightTemplateHyperlink;
And set their values in method paint() like so...
Dimension templateDimension = templateHyperlink.getPreferredSize();
xTemplateHyperlink = c.getWidth() - templateDimension.width - 5;
yTemplateHyperlink = 2;
widthTemplateHyperlink = templateDimension.width;
heightTemplateHyperlink = templateDimension.height;
which explains the code in method processMouseEvent().
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm attempting to make a Subclass to JLabel, which I named BlurPanel. I want the class to act like any normal swing container, only it must as default have a transparent background i.e. (setOpaque(false)) and it must blur the background of the parent frame. So far i've managed to blur BufferedImages and resized them, but when using standard swing layout managers i'm having a hard time at cropping the frame picture to the BlurPanels position. Does anyone have a good strategy to do this? Maybe it can be done without copying the underlying picture?
Use GlassPane Luke
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.WindowConstants;
/**
* Glass pane used to blur the content of the window.
*
* #author SMedvynskyy
*/
#SuppressWarnings("serial")
public class SplashGlassPane extends JPanel implements FocusListener {
/**
* Creates new GlassPane.
*/
public SplashGlassPane() {
addMouseListener(new MouseAdapter() {});
addMouseMotionListener(new MouseAdapter() {});
addFocusListener(this);
setOpaque(false);
setFocusable(true);
setBackground(new Color(0, 0, 0, 190));
}
#Override
public final void setVisible(boolean v) {
// Make sure we grab the focus so that key events don't go astray.
if (v) {
requestFocus();
}
super.setVisible(v);
}
// Once we have focus, keep it if we're visible
#Override
public final void focusLost(FocusEvent fe) {
if (isVisible()) {
requestFocus();
}
}
/**
* {#inheritDoc}
*/
#Override
public final void paint(Graphics g) {
final Color old = g.getColor();
g.setColor(getBackground());
g.fillRect(0, 0, getSize().width, getSize().height);
g.setColor(old);
super.paint(g);
}
#Override
public void focusGained(FocusEvent fe) {
// nothing to do
}
public static void main(String[] args) {
final JFrame frm = new JFrame("Test blurring");
frm.add(new JTextField("It's first component"), BorderLayout.NORTH);
frm.add(new JTextField("It's second component"), BorderLayout.SOUTH);
final JButton btn = new JButton("Start blur");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frm.getGlassPane().setVisible(true);
final Timer t = new Timer(5000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frm.getGlassPane().setVisible(false);
}
});
t.setRepeats(false);
t.start();
}
});
frm.add(btn);
frm.setSize(500, 400);
frm.setGlassPane(new SplashGlassPane());
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setVisible(true);
}
}
I am very new to Java AWT. My question header must seem ridiculous to you, sorry about that. In my application I have three buttons which display different threads when clicked on. Now I want to add maybe a button or checkboxes or choicelist, etc when clicked on a particular button. For eg, if I click on yes button, it should display a choice list, something like that. How do I achieve something like that? Here is my code so far:
import java.awt.Button;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class AppWindow extends Frame implements ActionListener{
String keymsg = "Test message";
String mousemsg = "Nothing";
int mouseX=30, mouseY=30;
String msg;
public AppWindow(){
//addKeyListener(new MyKeyAdapter(this));
//addMouseListener(new MyMouseAdapter(this));
addWindowListener(new MyWindowAdapter());
}
public void paint(Graphics g){
g.drawString(msg, 150, 100);
}
//Here the window is created:
public static void main(String args[]){
AppWindow appwin = new AppWindow();
appwin.setSize(new Dimension(300,200));
appwin.setTitle("My first AWT Application");
appwin.setLayout(new FlowLayout(FlowLayout.LEFT));
appwin.setVisible(true);
Button yes,no,maybe;
yes = new Button("yes");
no = new Button("no");
maybe = new Button("maybe");
appwin.add(yes);
appwin.add(no);
appwin.add(maybe);
yes.addActionListener(appwin);
no.addActionListener(appwin);
maybe.addActionListener(appwin);
}
#Override
public void actionPerformed(ActionEvent ae) {
// TODO Auto-generated method stub
String str = ae.getActionCommand();
if(str.equals("yes")){
msg = "You pressed Yes";
}
if(str.equals("no")){
msg = "You pressed No";
}
if(str.equals("maybe")){
msg = "You pressed Maybe";
}
repaint();
}
}
class MyWindowAdapter extends WindowAdapter {
public void windowClosing(WindowEvent we){
System.exit(0);
}
}
Points describing what you should be doing :
As already mentioned by others, better to use Swing over AWT, since Swing is more advanced.
As much as possible, always try to Paint on top of a JPanel or a
JComponent, instead of Painting right on top of your JFrame, by
overriding the paintComponent(Graphics g) method of the said
JComponent/JPanel
Never call setVisible(true) on the JFrame until and unless it's
size has been established. So in general terms, this has to be the
last call, once you are done adding components to the JFrame and
the size of the JFrame has been realized by the LayoutManager.
Inside your actionPerformed(...), instead of writing all if
statement blocks, you should adhere to the if-else if statement
blocks. The benefit of this, over the former is that, at any given
time, only one event will be fired, hence once the said condition is
satisfied, you don't want your code to keep checking other
conditions, which in general is really not a good programming
practice, IMHO.
MOST IMPORTANT THING : Never make calls like pack()/setVisible(...) from within the main method, such calls belong
to the Event Dispatch Thread, and must be done on the same. Please
read Concurrency in Swing for more detail.
Have a look at the example program, for better understanding.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ComponentExample
{
private CustomPanel drawingBoard;
private JPanel contentPane;
private JButton yesButton;
private JButton noButton;
private JButton maybeButton;
private JComboBox cbox;
private ActionListener buttonAction = new ActionListener()
{
#Override
public void actionPerformed(ActionEvent ae)
{
JButton button = (JButton) ae.getSource();
if (cbox.isShowing())
contentPane.remove(cbox);
if (button == yesButton)
{
drawingBoard.setText("You Pressed YES.");
contentPane.add(cbox, BorderLayout.PAGE_END);
}
else if (button == noButton)
drawingBoard.setText("You Pressed NO.");
else if (button == maybeButton)
drawingBoard.setText("You Pressed MAYBE.");
/*
* revalidate()/repaint() is needed
* when the JComponent is added or
* removed from the already
* visible Container.
*/
contentPane.revalidate();
contentPane.repaint();
}
};
public ComponentExample()
{
cbox = new JComboBox(
new String[]{"I GOT IT"
, "I STILL HAD DOUBT"});
}
private void displayGUI()
{
JFrame frame = new JFrame("Component Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = new JPanel();
contentPane.setOpaque(true);
contentPane.setBackground(Color.DARK_GRAY);
contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(5, 5));
JPanel buttonPanel = new JPanel();
buttonPanel.setOpaque(true);
buttonPanel.setBackground(Color.WHITE);
yesButton = new JButton("YES");
yesButton.addActionListener(buttonAction);
noButton = new JButton("NO");
noButton.addActionListener(buttonAction);
maybeButton = new JButton("MAY BE");
maybeButton.addActionListener(buttonAction);
buttonPanel.add(yesButton);
buttonPanel.add(noButton);
buttonPanel.add(maybeButton);
contentPane.add(buttonPanel, BorderLayout.PAGE_START);
drawingBoard = new CustomPanel();
contentPane.add(drawingBoard, BorderLayout.CENTER);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new ComponentExample().displayGUI();
}
});
}
}
class CustomPanel extends JPanel
{
private String msg;
public CustomPanel()
{
msg = "";
setOpaque(true);
setBackground(Color.WHITE);
}
public void setText(String msg)
{
this.msg = msg;
repaint();
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(300, 300));
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawString(msg, getWidth() / 3, getHeight() / 3);
}
}
I don't know if I have understood the question well but... couldn't you create those elements and call their setVisible(boolean) methods to make them not visible at first, and them make them visible when user pushes buttons?
I am using a simple Pomodoro timer but I have no sound/speakers, and so I'd like to signal the end of the timer by simply blanking the screen with a specified color, then toggling it a few times with another color. As if I made my monitor a left-turn car signal. How do I control the monitor like that? Is there some win32 code for this?
I'm familiar with Java, and much less with c# or C++
I'm not sure what is the motive to control the whole screen. Maybe more appropriate would be to show a notification in the system tray.
Anyhow, using Java you could popup a JFrame in full screen mode. Change its background using a timer a couple of times and then close it. Here is a simplified example that demos something similar :
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
class FullScreenFrame extends JFrame{
private static final int MAX_COUNT = 3;
private static final int PERIOD = 1000;
private JPanel panel;
private int count;
public FullScreenFrame(){
super();
setUndecorated(true);
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "ESCAPE");
getRootPane().getActionMap().put("ESCAPE", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
dispose();
}
});
panel = new JPanel();
panel.setBackground(Color.GREEN);
add(panel);
new Timer(PERIOD, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (count < MAX_COUNT) {
if (count % 2 == 0){
panel.setBackground(Color.BLACK);
} else {
panel.setBackground(Color.GREEN);
}
count++;
} else {
((Timer) e.getSource()).stop();
dispose();
}
}
}).start();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
FullScreenFrame frame = new FullScreenFrame();
frame.setBounds(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().getBounds());
frame.setAlwaysOnTop(true);
frame.setVisible(true);
}
});
}
}