I'm creating a text adventure and I need to completely disable the mouse cursor. Not just hide it, although I already know how to do that, but disable it completely so that you must use Alt-Tab or a built-in quit button to stop. The main reason for this is because people can scroll with the mouse cursor and I need to disable that, I thought about canceling MouseEvents when they're fired but I couldn't get it to work (the listener that is.)
If someone knows how then please speak up and tell me! :)
EDIT: Whoops, I forgot my code. Here is my Console class.
This is started by another class with new Console();
EDIT 2: Here are some snippets of me trying to create an invisible cursor and a mouse listener. The first one works, but the latter does not.
// Invisible cursor
Toolkit toolkit = Toolkit.getDefaultToolkit();
Point hotSpot = new Point(0,0);
BufferedImage cursorImage = new BufferedImage(1, 1, BufferedImage.TRANSLUCENT);
Cursor invisibleCursor = toolkit.createCustomCursor(cursorImage, hotSpot, "InvisibleCursor");
frame.setCursor(invisibleCursor);
// Adding mouse listener
frame.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
System.out.println(me);
}
});
EDIT 3: To elaborate on the mouse listener it simply does not work. It doesn't print anything.
If you just want to prevent users from seeing old text, remove the old text from the JTextArea.
The easiest way to do it is to leave the JTextArea in a JScrollPane, and keep track of the lines yourself:
private static final int MAX_VISIBLE_LINES = 12;
private final Deque<String> lines = new LinkedList<>();
void appendLine(String line,
JTextArea textArea) {
lines.addLast(line);
if (lines.size() > MAX_VISIBLE_LINES) {
lines.removeFirst();
}
String text = String.join("\n", lines);
textArea.setText(text);
textArea.setCaretPosition(text.length());
try {
textArea.scrollRectToVisible(
textArea.modelToView(text.length()));
} catch (BadLocationException e) {
throw new RuntimeException(e);
}
}
Trying to commandeer the mouse on a multitasking desktop is just going to make users angry. Would you want an application preventing you from reading your e-mail?
Update:
If you want to base the number of lines of text on the JTextArea’s current height, use the JTextArea’s font metrics. I assume you don’t need to get it exactly right and it’s okay if the number is off by one or two lines. (To account for things like line wrapping would be considerably more difficult.)
private final Deque<String> lines = new LinkedList<>();
void appendLine(String line,
JTextArea textArea) {
FontMetrics metrics = textArea.getFontMetrics(textArea.getFont());
JViewport viewport = (JViewport) textArea.getParent();
int visibleLineCount = viewport.getExtentSize().height / metrics.getHeight();
lines.addLast(line);
while (lines.size() > visibleLineCount) {
lines.removeFirst();
}
String text = String.join("\n", lines);
textArea.setText(text);
textArea.setCaretPosition(text.length());
try {
textArea.scrollRectToVisible(
textArea.modelToView(text.length()));
} catch (BadLocationException e) {
throw new RuntimeException(e);
}
}
Related
This question already has answers here:
Java - checking if parseInt throws exception
(8 answers)
Closed 1 year ago.
So I tried to look a bit in forums and StackOverflow but nothing worked for me I need when enter is pressed to stop my code this is my code `
JFrame f;
JTextField I;
// JButton
JToggleButton b;
// label to display text
JLabel l;
f = new JFrame("AutoClicker");
i = new JTextField("100");
// create a label to display text
l = new JLabel("clicks/seconds");
// create a new buttons
b = new JToggleButton("Start");
// create a panel to add buttons
JPanel p = new JPanel();
// add buttons and textfield to panel
p.add(b);
p.add(i);
p.add(l);
// setbackground of panel
p.setBackground(Color.red);
// add panel to frame
f.add(p);
// set the size of frame
f.setSize(280, 80);
f.setVisible(true);
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int jml = Integer.parseInt(i.getText());
if(jml < 50)
{
jml = 50;
}
AutoClicker(jml);
}
});
}
static void AutoClicker(int jml)
{
while(true)
{
try{
Robot r = new Robot();
int button = InputEvent.BUTTON1_DOWN_MASK;
r.mousePress(button);
Thread.sleep(jml);
r.mouseRelease(button);
Thread.sleep(jml);
}
catch(Exception e){
e.printStackTrace();
System.out.println("not good");
}
}
}
}`
I tried to add a KeyListener but it did not work.
I don't understand why it doesn't work so if you can just help me know why it doesn't work it would be much apreciated.
KeyListener isn't going to solve the problem of the fact that you are simply not handling the potential of Integer.parseInt to throw an exception - I mean, how can it convert "" or "This is not a number" to an int. In those cases it throws an exception
The JavaDocs clearly state
Throws:NumberFormatException - if the string does not contain a
parsable integer.
Go back and have a look at the original error you were getting from your previous question on this exact topic
java.lang.NumberFormatException: For input string: "Enter"
It's telling you exactly what the problem is - the text "Enter" can not be converted to an int value.
YOU have to handle this possibility. No offence, but this is honestly basic Java 101. See Catching and Handling Exceptions
Another option which "might" help is to use a formatted text field
You also don't seem to have a firm grip on the concept of what a "event driven environment" is or what the potential risk of what doing something like while (true) will do if executed within the context of the Event Dispatching Thread. This makes me think you've got yourself in over all head.
You're going to want to learn about Concurrency in Swing as AutoClicker should never be called within the context of the Event Dispatching Thread, which is going to lead you another area of complexity, concurrency and all the joys that brings.
Updated
Wow, you changed the title. Maybe a better description of the problem you're trying to solve would have a gotten a better answer. In short, you can't, not natively in Java anyway. The only way you can detect keyboard input out side of the app is using native integration, JNA/JNI. Plenty of examples about, for example
I'm writing a plugin for a miscropy program and have problems with the repaint() method.
short question:
Is there any way to get informed as soon as the repaint of a JPanel was done or synchronize the code with it?
detailed version:
My program can plot a set of data in a xy-chart to a JPanel and show it using jfree.chart; In another part of the programm I have many datasets (~100) that I want to plot and save as images. I've also found a solution, but I really don't like it. The Problem can be reduced to a notification about the paint status of a JPanel.
In the part that shall save all images I have this solution:
PlotSpectrum spectrumWindow = getTheWindow(); //pseudo code...
// some stuff
ti = storage.getImage(channel, slice, frame, position);
spectrumWindow.plotData(false, andor.captureSpectrum(ti.pix), wave,
centerWave, fineGrating, exposureTime,
slitWidth, substractBackground);
spectrumWindow.repaint(); // probably not necessary
sleep(100); // this annoys me...
spectrumWindow.savePlot(path, true, config, null);
spectrumWindow is a JPanel that is also displayed in another window and it all works fine.
BUT I really don't like that sleep(100) in there... without it I'm asking for a repaint but it isn't done till I try to save a "snapshot" of (thats what savePlot is doing...). I know, other Thread and these damn synchronization problems...
With the sleeping I'm just making it unnecessary slow and if I wait not long enough the images are not completly drawn (eg lower half missing)
Is there any way to get informed as soon as the repaint was done? I probably would be also fine with a Listener, better would be a solution with a monitor or sth comparable or a method that is repainting NOW (doesn't exists as far I know?)
The main GUI (include the JPanel spectrumWindow) and the earlier pasted code are running in different Threads.
The probably also important parts of my code are following here. Please excuse if some brackets aren't matching or some variables aren't declared, I removed very much code.
thanks
schetefan24
class PlotSpectrum extends ApplicationFrame // that extends JFrame
{
public void plotData(boolean backgroundGiven, int[] spect, double[] wave_,
double centerWave, boolean fineGrating_, double exposureTime,
double slitWidth, boolean substractBackground)
{
//process data and store internally
replot();
}
private void replot()
{
XYSeries series = new XYSeries("Spectrum");
//add data to series
XYSeriesCollection collection = new XYSeriesCollection(series);
//setting up some labels and such stuff...
JFreeChart chart = ChartFactory.createXYLineChart(
title,
"Wavelength [nm]",
yLabel,
collection,
PlotOrientation.VERTICAL,
false,
false,
false
);
dataPanel.add(new ChartPanel(chart)); // this is contained in a Frame
}
public void savePlot(String path, boolean overWriteAll, HashMap<String,String> config, int[][] addData)
{
File output = new File(path);
//some more stuff, ask overwrite etc
if(image)
{
BufferedImage im = createImage();
String extension = path.substring(path.lastIndexOf(".")+1, path.length());
ImageIO.write(im, extension, output);
} else {
//that is an textexport, works fine
}
}
public BufferedImage createImage()
{
JPanel panel = (JPanel) flipChart.getSelectedComponent();
int w = panel.getWidth();
int h = panel.getHeight();
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bi.createGraphics();
panel.paint(g);
return bi;
}
}
that I want to plot and save as images.
add the data to a non visible panel.
create a BufferedImage of the panel
create an ImageIcon using the Image from above
update a JLabel (that has already been added to the frame) using the setIcon(...) method
the above step should generate a PropertyChange event when the Icon changes. You can use a ProperChangeListener to listen for this event. When you receive the event you can repeat steps 1 - 4.
Check out Screen Image. It will help you create an image of a non-visible component.
Note, you don't really need steps 4-5. I just added them so you have a visual of the plots as they are being processed. If you don't want the visual then maybe you just display text on a JLabel indicating which plot is currently being converted.
I am trying to execute the lines:
Balldemo bd = new BallDemo();
bd.bounce(myInt);
In the below code:
public void actionPerformed(ActionEvent evt) {
String text = textField.getText();
try {
myInt=Integer.parseInt(textField.getText());
BallDemo bd = new BallDemo();
bd.bounce(myInt);
int newInt = myInt + 5;
System.out.println("Integer is: "+newInt);
}
catch (NumberFormatException ex) {
System.out.println("Not a number");
}
//Make sure the new text is visible, even if there
//was a selection in the text area.
textArea.setCaretPosition(textArea.getDocument().getLength());
}
But is does not boot the program correctly as follows:
program is a canvas with two balls that move, bounce(int numberOfBalls) will draw the balls on the canvas and start them moving.
In the above code, the canvas is created but the balls do not appear.
However, in a different class under the main method it works fine.
Basically don't understand why it won't successfully execute in a try-catch loop.
I suspect your BallDemo object (bd) is going out of scope as soon as the try block ends. Try declaring it outside the try block.
I'm trying to work with a non-editable JTextArea added to a JScrollPane. I want a line to be highlighted when the user clicks on that specific line. I could implement this part using the following code:
public static void initHighlightOption(final JTextArea textArea){
textArea.setFont(new Font("Courier New", Font.PLAIN, 12));
textArea.setEditable(false);
final Action selectLine = getAction(textArea, DefaultEditorKit.selectLineAction);
textArea.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 1) {
selectLine.actionPerformed(null);
}
});
textArea.setSelectionStart(0);
textArea.setSelectionEnd(0);
}
public static Action getAction(JTextArea textArea, String name) {
Action action = null;
Action[] actions = textArea.getActions();
for (int i = 0; i < actions.length; i++) {
if (name.equals(actions[i].getValue(Action.NAME).toString())) {
action = actions[i];
break;
}
}
return action;
}
What I want to add is that once a line is highlighted and user scrolls up/down using keyboard up/down key, i want the current line to be highlighted. Is this possible by adding a keyListener? I'm stuck on how highlight data while scrolling up.
The text area contains data like this:
Line1
Line2
Line3
Line4
Line5
(i.e. there might be new lines between two particular lines of data)
What your asking for is not so easy to do. First off use a JTextPane instead of a JTextArea, it'll be much easier to handle. You will be need to get the Highlighter object from it
Highlighter hl = textPane.getHighlighter();
and you would probably have to keep track of your caret position each time the user scrolls with the arrow keys. When doing that you need to programatically change the highlights; something like:
Highlighter.Highlight myHighlight = null;
Highlighter.Highlight[] highlights = textPane.getHighlighter().getHighlights();
myHighlight = highlights[0]; //assuming there is one only
try {
hl.changeHighlight(myHighlight, myHighlight.getStartOffset()+1, myHighlight.getEndOffset());
}
catch(BadLocationException e) {
e.printStackTrace();
}
You can probably put this in your onKeyReleased() method. You kind of get the idea of what you're going to have to do. Read up on using JTextPane and Highlighter classes in the Java API docs, it will really help you alot.
I'm developing a small calculator widget that keeps a running log of calculations. It's supposed to scroll to the bottom of the log every time a new entry is added. This part seems to be working fine.
The problem is, when I press a calculator button that does not add to the log, the log pane always scrolls back to the top, and the scrollbar disappears. How can I keep it from doing this?
The code that adds to the log is:
private JTextPane logArea; //This is placed inside a JScrollPane
private void log(String m, SimpleAttributeSet a) {
int len = logArea.getDocument().getLength();
logArea.setEditable(true);
logArea.setCaretPosition(len);
logArea.setCharacterAttributes(a, false);
logArea.replaceSelection(m);
logArea.scrollRectToVisible(new Rectangle(0,logArea.getBounds(null).height,1,1));
logArea.setEditable(false);
}
The code that seems to be messing with the scroll is:
private void addDigit(char digit) {
if (clearDisplayBeforeDigit) {
clearNumDisplay();
}
if (numInDisplay.getText().length() < maxNumDigits) {
if (digit == '.') { //Point
if (!hasPoint) { //Only one point allowed
hasPoint = true;
String newText = numInDisplay.getText() + ".";
numInDisplay.setText(newText);
}
} else { //New digit
String newText = numInDisplay.getText() + digit;
numInDisplay.setText(newText);
}
}
}
The code you think is causing the problem doesn't even reference the logArea, so why would you think this causes the problem?
You don't need to use the scrollRectToVisible(...) method. The setCaretPosition(...) should do the trick. Although you should get the length of the document and invoke that method AFTER you update the document.
Check out Text Area Scrolling for more information.
Edit:
I also don't see any reason for changing the editability of the text area.