JavaFX target drag event null - java

I have a for loop that creates multiple rectangle shapes and I am adding DragDropped events to them. For some reason even though the source reports it as successful (and the color of the rectangle changes) when I go to check the target it is reported as null.
ParkingSpot is just an class that extends Rectangle and adds a new more bits of info I need to store in them.
Also, TransferMode.COPY is set on the source and target(ParkingSpot) so that shouldn't be an issue.
private ParkingSpot createRectangle(double x, double y, double width, double height){
ParkingSpot vehicleSpot = new ParkingSpot(x, y, width, height);
...
spot.setOnDragDropped(event -> {
System.out.println("onDragDropped");
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasString()) {
spot.setTestinfo(db.getString());
System.out.println( " added to " + spot.getTestinfo());
spot.setFill(Color.BLUE);
success = true;
}
event.setDropCompleted(success);
event.consume();
});
}
In this spot.setFill(Color.BLUE); works but for some reason spot.getTestinfo() doesn't. The same goes with me using spot.getX() which also works. I don't understand how it could set the color but not the text. My apologies if this is a bit brief. I can add more if needed.
EDIT: This is how I am creating the rectangles:
for (ParkingSpot spot : parkingSpots){
pane.getChildren().add(createDraggableRectangle(spot.getX(), spot.getY(), spot.getWidth(), spot.getHeight()));
}
This loops through a List of ParkingSpots and adds them to the list for saving and loading.
These are the ListView items and how I copy their info to the dragboard. I know this works as when I drop it onto the shape I have it output the contents it dropped.
listCell.setOnDragDetected(event -> {
/* drag was detected, start a drag-and-drop gesture*/
/* allow any transfer mode */
Dragboard db = listCell.startDragAndDrop(TransferMode.COPY);
/* Put a string on a dragboard */
ClipboardContent content = new ClipboardContent();
content.putString(listCell.getText());
db.setContent(content);
System.out.println("Dragging" + content);
event.consume();
});
Everything here is in my Controller.java class.
Thanks!

Related

Drag and drop only triggers from the bottom of the Actor Libgdx

I have a table which contains in every cell another table. For example that table can have inside 8 other tables. I added a drag and drop so I can drag the smaller tables. It works but only partially. The drag and drop only gets detected if I touch on the bottom of the smaller tables, it doesn't trigger if I touch on the middle of them or on the top. I tried to set the width and height of the smaller tables, and then the drag and drop also triggers from a point on the top, but still not from everywhere it should? What could be wrong?
My code:
In code, collectionTable is the bigger table and TestCard are the types of the smaller tables that get added to collectionTable.
dnd = new DragAndDrop();
dnd.setDragTime(50);
for (final Actor x : collectionTable.getChildren()) {
TestCard y = (TestCard) x;
y.setWidth(Gdx.graphics.getWidth() / (7 * scale));
y.setHeight(Gdx.graphics.getHeight() / (3.3f * scale));
dnd.addSource(new CardSource(y));
dnd.addTarget(new Target(selectedDeck);
//not adding the code from the target as it works as intended
class CardSource extends Source {
final Payload payload = new Payload();
TestCard card;
public CardSource(Actor actor) {
super(actor);
}
public CardSource(TestCard card) {
super(card);
this.card = card;
card.setWidth(Gdx.graphics.getWidth() / (7 * scale));
card.setHeight(Gdx.graphics.getHeight() / (3.3f * scale));
}
public Payload dragStart(InputEvent event, float x, float y, int pointer) {
payload.setObject(card.);
payload.setDragActor(new TestCard(card));
//payload.setInvalidDragActor(invalidActor);
payload.setValidDragActor(new TestCard(card));
return payload;
}
}
use: setTouchabe(Touchable.enabled)
on the parent table. By default a 'group' (WidgetGroup or Table) only register touch on actual visible actors like buttons and labels.

JavaFX GridPane Drag and Drop with a dynamic amount of Labels

At the moment I am struggling with a JavaFX problem. I will try to explain it as detailed as possible. If you need any further information, just let me know!
What do I want to achieve:
In the picture below you can see what I am trying to achive
I am creating a variable number of Labels (the amount will differ from time to time)
The references to this labels are stored in an ArrayList. The Labels then are placed on the GridPane
Now I want to be able to drag and drop that Labels in the GridPane
I would like to achieve a solution like in the picture below
When you drag a Label it should be visually shown, where I am dragging it to
When passing another Label the visual effect should show, what happens when I drop it here (nr. 3 in the picture). After I drop the Label there, the Labels on the right are switching their position one field to the right. The opened space where I took the source have to be filled with the Labels on the right.
Here is the picture of what I am dreaming right now
At the moment I am able to create the Labels and place them on the GridPane. But when I try to use an inner class for the .onDragListener I am getting the message, that the Label has to be final. But I can't make it final, because it was created during the runtime and the references are stored in an ArrayList.
Okay here is some Code. I hope it helps.
public class Center {
public static GridPane createCenterContent(List<Tour> tourList){
GridPane gridPaneCenter = new GridPane();
final List<List<Label>> customerLabelList = new ArrayList<List<Label>>();
Label customerLabel = new Label();
for(int i = 0 ; i < tourList.size() ; i++){
customerLabelList.add(i, new ArrayList<Label>());
for(int j = 0 ; j < tourList.get(i).getTour().size() ; j++){
customerLabelList.get(i).add(new Label(tourList.get(i).getTour().get(j).getVorname() + " " + tourList.get(i).getTour().get(j).getNachname() + " \n" +
tourList.get(i).getTour().get(j).getStrasse() + " \n" + tourList.get(i).getTour().get(j).getAdresse()));
customerLabelList.get(i).get(j).getStyleClass().add("kdLabelGridLayout");
customerLabelList.get(i).get(j).setMinWidth(200);
customerLabelList.get(i).get(j).setMinHeight(100);
customerLabel = customerLabelList.get(i).get(j);
customerLabel.setOnDragDetected(new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
/* drag was detected, start a drag-and-drop gesture*/
/* allow any transfer mode */
Dragboard db = customerLabel.startDragAndDrop(TransferMode.ANY);
System.out.println("Label wird bewegt!");
}
});
customerLabelList.get(i).get(j).setOnDragOver(new EventHandler<DragEvent>() {
public void handle(DragEvent event) {
/* data is dragged over the target */
/* accept it only if it is not dragged from the same node
* and if it has a string data */
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
System.out.println("Label berührt anderes Label");
}
});
gridPaneCenter.add(customerLabelList.get(i).get(j), i, j, 1, 1);
}
}
gridPaneCenter.setHgap(10);
gridPaneCenter.setVgap(10);
return gridPaneCenter;
}
}
I am getting an error on the Dragboard db = customerLabel.startDragAndDrop(TransferMode.ANY); line. Eclipse tells me that the variable has to be final.
I have a List which contains Lists of Labels. I am placing that Labels in the GridPane and trying to give them all the drag and drop listeners. The amount of labels in the List> differs from time to time.
What can I do to solve the problem? I am very thankful for any hint or link you guys can provide me with.

How are If statements on the same level both executed in an Android/Java Program?

Currently, I am going over the code given to us for an Android program called PaintPot, which allows the users to finger paint on their Android devices.
This code handles the events that will happen when the screen is tapped, buttons are clicked, etc.
// Here is the event dispatcher for our app. We need to Override the method for the Form
// superclass
#Override
public boolean dispatchEvent(Component component, String id, String eventName,
Object[] args) {
//if the canvas is touched by a tapping finger
if (component.equals(myCanvas) && eventName.equals("Touched")) {
canvasTouced(((Float) args[0]).intValue(), ((Float) args[1]).intValue());
return true;
//if the canvas is touched by a dragging finger, paint the line this way
} else if (component.equals(myCanvas) && eventName.equals("Dragged")) {
drawLine(((Float) args[2]).intValue(),
((Float) args[3]).intValue(),
((Float) args[4]).intValue(),
((Float) args[5]).intValue());
return true;
//if the canvas is touched while the blue button is selected
} else if (component.equals(btnBlue) && eventName.equals("Click")) {
myCanvas.PaintColor(COLOR_BLUE);
return true;
//if the canvas is touched while the green button is selected
} else if (component.equals(btnGreen) && eventName.equals("Click")) {
myCanvas.PaintColor(COLOR_GREEN);
return true;
//if the canvas is touched while the red button is selected
} else if (component.equals(btnRed) && eventName.equals("Click")) {
myCanvas.PaintColor(COLOR_RED);
return true;
//if the wipe button is selected
} else if (component.equals(btnWipe) && eventName.equals("Click")) {
myCanvas.Clear();
return true;
}
return false;
}
The code works fine and does what I want it to "as-is." But what I don't really understand is that the if statement for if the user taps or drags his or her finger across the canvas is on "the same level" or within the same if statement if the color buttons are selected. Shouldn't it be when the user taps or drags his finger across the screen, the same code that determines if a line or a dot that is made should also ask for what color the line or dot should be, rather than just size of the dot, depending on what color button is selected?
For a more complete reference, here is the entire code, if anyone is curious:
import android.graphics.Color;
import com.google.devtools.simple.runtime.components.android.Button;
import com.google.devtools.simple.runtime.components.Component;
import com.google.devtools.simple.runtime.components.HandlesEventDispatching;
import com.google.devtools.simple.runtime.components.android.Canvas;
import com.google.devtools.simple.runtime.components.android.Form;
import com.google.devtools.simple.runtime.components.android.HorizontalArrangement;
import com.google.devtools.simple.runtime.components.android.Label;
import com.google.devtools.simple.runtime.events.EventDispatcher;
import java.util.Random;
public class PaintPotActivity extends Form implements HandlesEventDispatching {
private Canvas myCanvas; //creates a canvas object
private Label lblStatus; //creates a label that discusses the status of the program
private Button btnRed; //creates a button for red paint
private Button btnBlue; // "" for blue paint
private Button btnGreen; // "" for green paint
private Button btnWipe; //creates a button that wipes the screen clean
private Button btnDotSize; // creates a button that changes the dot size
// Variable (field) used to for displaying number of touches
int numTouches; //declares an integer that lists out the number of touches a user made
// The equivalent to a "main" method for App Inventor apps is the $define method.
void $define() {
//We are going to place the color buttons in a HorizontalArrangement
HorizontalArrangement hr = new HorizontalArrangement(this);
btnRed = new Button(hr);
btnBlue = new Button(hr);
btnGreen = new Button(hr);
//set their color
btnRed.BackgroundColor(Color.RED);
btnBlue.BackgroundColor(Color.BLUE);
btnGreen.BackgroundColor(Color.GREEN);
//set the button text
btnRed.Text("Red");
btnBlue.Text("Blue");
btnGreen.Text("Green");
//canvas into its own HorizontalArrangement
hr = new HorizontalArrangement(this);
myCanvas = new Canvas(hr);
myCanvas.Width(400);
myCanvas.Height(400);
myCanvas.LineWidth(10);
//Wipe and a label into its own HorizontalArrangement
hr = new HorizontalArrangement(this);
btnWipe = new Button(hr);
btnWipe.Text("Wipe");
lblStatus = new Label(hr);
lblStatus.Text(" touchX/touchY:");
// Register for events. By the second argument can be any string. The third argument must
// exactly match the name of the event that you want to handle for that component. When the event
// happens, dispatchEvent will be called with these arguments.
EventDispatcher.registerEventForDelegation(this, "JavaBridge", "Touched");
EventDispatcher.registerEventForDelegation(this, "JavaBridge", "Click");
EventDispatcher.registerEventForDelegation(this, "JavaBridge", "Dragged");
}
// Here is the event dispatcher for our app. We need to Override the method for the Form
// superclass
#Override
public boolean dispatchEvent(Component component, String id, String eventName,
Object[] args) {
//if the canvas is touched by a tapping finger
if (component.equals(myCanvas) && eventName.equals("Touched")) {
canvasTouced(((Float) args[0]).intValue(), ((Float) args[1]).intValue());
return true;
//if the canvas is touched by a dragging finger, paint the line this way
} else if (component.equals(myCanvas) && eventName.equals("Dragged")) {
drawLine(((Float) args[2]).intValue(),
((Float) args[3]).intValue(),
((Float) args[4]).intValue(),
((Float) args[5]).intValue());
return true;
//if the canvas is touched while the blue button is selected
} else if (component.equals(btnBlue) && eventName.equals("Click")) {
myCanvas.PaintColor(COLOR_BLUE);
return true;
//if the canvas is touched while the green button is selected
} else if (component.equals(btnGreen) && eventName.equals("Click")) {
myCanvas.PaintColor(COLOR_GREEN);
return true;
//if the canvas is touched while the red button is selected
} else if (component.equals(btnRed) && eventName.equals("Click")) {
myCanvas.PaintColor(COLOR_RED);
return true;
//if the wipe button is selected
} else if (component.equals(btnWipe) && eventName.equals("Click")) {
myCanvas.Clear();
return true;
}
return false;
}
/**
* This method will get the touched touchX, touchY coordinates and will then create a circle
* of random radius (between 1 to 33) with the color that was selected (RED, BLUE or GREEN).
* It will also display the touched touchX,touchY coordinates.
* #param x current x
* #param y current y
*/
private void canvasTouced(int x, int y) {
myCanvas.DrawCircle(x, y, new Random().nextInt(33));
lblStatus.Text(" touchX/touchY:" + x + "/" + y + " touches: " + ++numTouches);
}
/**
* Method to draw line
* #param prevX last touch x
* #param prevY last touch y
* #param touchX current x
* #param touchY current y
*/
private void drawLine(int prevX, int prevY, int touchX, int touchY) {
myCanvas.DrawLine(prevX, prevY, touchX, touchY);
}
}
dispatchEvent is called as the application fires events. Separate events get thrown for each button click and interaction with the app. Each of the if statements is determining how different types of events get handled.
Shouldn't it be when the user taps or drags his finger across the screen, the same code that determines if a line or a dot that is made should also ask for what color the line or dot should be, rather than just size of the dot, depending on what color button is selected
In this case, state between events is being saved in the myCanvas - clicking btnBlue sets the paint color to blue on the canvas (myCanvas.PaintColor(COLOR_BLUE);) then waits for another event to happen. If the user then drags across the canvas, a line is drawn (ultimately myCanvas.DrawLine(prevX, prevY, touchX, touchY);). Since myCanvas remembers the state, it draws the line in blue.
if statement for if the user taps or drags his or her finger across
the canvas is on the same level
Well, I may be wrong but if by the same level you mean some kind of equal weightage to user's action then answer is yes.
Shouldn't it be when the user taps or drags his finger across the
screen, the same code that determines if a line or a dot that is made
should also ask for what color the line or dot should be, rather than
just size of the dot, depending on what color button is selected
Yes, it should. For this, you will have to program accordingly.
This is a common construct for event handling. It might help to think of the 'same-level' IFs as options the user may select. When you have two buttons on the same dialog, you don't typically nest them because you can not know which one will be clicked.
The name of the method, 'dispatchEvent' is a big clue, all it is doing is receiving the event and choosing the appropriate code path. Normally each IF just turns around and calls a function or method otherwise the dispatch method can become huge.
If you have a large enough enumeration for all possible messages (Win32 does this), you can do the same thing with a 'switch/case' statement instead of all the IFs.

How to implement freeze column in GXT 3.x?

How can frozen columns be implemented in GXT 3.x (from Sencha)? Ext-JS, another product from Sencha seems to implement this, but I can't see where the Java based GXT implement the same thing:
http://dev.sencha.com/deploy/ext-4.0.0/examples/grid/locking-grid.html
The basic idea is that you need two different scrolling containers, one with the fixed column(s), one with the scrolling columns. Each of these need to be in a distinct viewport, so the standard Grid/GridView doesn't work well with this - they make assumptions about how scrolling should behave, so simply subclassing one or both is likely to be fairly involved.
Instead, you can build two grids, one for the locked columns, one for the scrolling ones. Each can deal with their own ColumnConfig classes, to draw headers and rows, and will be linked to the same ListStore to ensure their data is in sync - changes in the store will be passed along to both listening grids.
To get the full effect, some additional wiring will be needed:
Linking scrolling. Listen to the BodyScrollEvent from each Grid, and scroll the other to the same place (changing only top, not left, since you don't want one to control the other).
Sizing is the second big piece - both grids need their scrollable height to be the same, but the horizontal scrolling one needs a buffer on the bottom when it is actually showing that scrollbar. Usually the Grid is told to size based on its parent's instructions, though sometimes you directly size the Grid - in this case, this step is not needed, just size the two grids slightly differently. Otherwise, you'll need to structure the layout to properly configure this.
Finally, the locked column needs its vertical scrollbar to be hidden away - the user has no need to see two vertical scrollbars.
This covers the basic use case, but doesn't deal with things like alternate GridView implementations - GroupingView and subclasses will need to link expanding (and to hide the group headings so they don't appear twice, plus deal with the fact that the group row shouldn't get split when the second half scrolls sideways), TreeGridView and TreeGrid will need to link expanding nodes and hide the tree +/- icons from the second grid.
Here's this basic set of modifications applied to the basic grid example at http://www.sencha.com/examples/#ExamplePlace:basicgrid. To help avoid confusing the issue, I've deleted a number of other features in that grid such as tooltips and changing the selection model:
public class GridExample implements IsWidget, EntryPoint {
private static final StockProperties props = GWT.create(StockProperties.class);
private ContentPanel root;
#Override
public Widget asWidget() {
if (root == null) {
final NumberFormat number = NumberFormat.getFormat("0.00");
ColumnConfig<Stock, String> nameCol = new ColumnConfig<Stock, String>(props.name(), 50, SafeHtmlUtils.fromTrustedString("<b>Company</b>"));
ColumnConfig<Stock, String> symbolCol = new ColumnConfig<Stock, String>(props.symbol(), 100, "Symbol");
ColumnConfig<Stock, Double> lastCol = new ColumnConfig<Stock, Double>(props.last(), 75, "Last");
ColumnConfig<Stock, Double> changeCol = new ColumnConfig<Stock, Double>(props.change(), 100, "Change");
changeCol.setCell(new AbstractCell<Double>() {
#Override
public void render(Context context, Double value, SafeHtmlBuilder sb) {
String style = "style='color: " + (value < 0 ? "red" : "green") + "'";
String v = number.format(value);
sb.appendHtmlConstant("<span " + style + " qtitle='Change' qtip='" + v + "'>" + v + "</span>");
}
});
ColumnConfig<Stock, Date> lastTransCol = new ColumnConfig<Stock, Date>(props.lastTrans(), 100, "Last Updated");
lastTransCol.setCell(new DateCell(DateTimeFormat.getFormat("MM/dd/yyyy")));
List<ColumnConfig<Stock, ?>> l = new ArrayList<ColumnConfig<Stock, ?>>();
//Remove name from main set of columns
// l.add(nameCol);
l.add(symbolCol);
l.add(lastCol);
l.add(changeCol);
l.add(lastTransCol);
//create two column models, one for the locked section
ColumnModel<Stock> lockedCm = new ColumnModel<Stock>(Collections.<ColumnConfig<Stock, ?>>singletonList(nameCol));
ColumnModel<Stock> cm = new ColumnModel<Stock>(l);
ListStore<Stock> store = new ListStore<Stock>(props.key());
store.addAll(TestData.getStocks());
root = new ContentPanel();
root.setHeadingText("Locked Grid Sample");
root.setPixelSize(600, 300);
final Resizable resizable = new Resizable(root, Dir.E, Dir.SE, Dir.S);
root.addExpandHandler(new ExpandHandler() {
#Override
public void onExpand(ExpandEvent event) {
resizable.setEnabled(true);
}
});
root.addCollapseHandler(new CollapseHandler() {
#Override
public void onCollapse(CollapseEvent event) {
resizable.setEnabled(false);
}
});
//locked grid
final Grid<Stock> lockedGrid = new Grid<Stock>(store, lockedCm) {
#Override
protected Size adjustSize(Size size) {
//this is a tricky part - convince the grid to draw just slightly too wide
//and so push the scrollbar out of sight
return new Size(size.getWidth() + XDOM.getScrollBarWidth() - 1, size.getHeight());
}
};
lockedGrid.setView(new GridView<Stock>(){{
this.scrollOffset=0;
}});
//require columns to always fit, preventing scrollbar
lockedGrid.getView().setForceFit(true);
//main grid, with horiz scrollbar
final Grid<Stock> grid = new Grid<Stock>(store, cm);
//don't want this feature, want to encourage horizontal scrollbars
// grid.getView().setAutoExpandColumn(nameCol);
grid.getView().setStripeRows(true);
grid.getView().setColumnLines(true);
grid.setBorders(false);
grid.setColumnReordering(true);
grid.setStateful(true);
grid.setStateId("gridExample");
//link scrolling
lockedGrid.addBodyScrollHandler(new BodyScrollHandler() {
#Override
public void onBodyScroll(BodyScrollEvent event) {
grid.getView().getScroller().scrollTo(ScrollDirection.TOP, event.getScrollTop());
}
});
grid.addBodyScrollHandler(new BodyScrollHandler() {
#Override
public void onBodyScroll(BodyScrollEvent event) {
lockedGrid.getView().getScroller().scrollTo(ScrollDirection.TOP, event.getScrollTop());
}
});
HorizontalLayoutContainer gridWrapper = new HorizontalLayoutContainer();
root.setWidget(gridWrapper);
//add locked column, only 300px wide (in this example, use layouts to change how this works
HorizontalLayoutData lockedColumnLayoutData = new HorizontalLayoutData(300, 1.0);
//this is optional - without this, you get a little offset issue at the very bottom of the non-locked grid
lockedColumnLayoutData.setMargins(new Margins(0, 0, XDOM.getScrollBarWidth(), 0));
gridWrapper.add(lockedGrid, lockedColumnLayoutData);
//add non-locked section, taking up all remaining width
gridWrapper.add(grid, new HorizontalLayoutData(1.0, 1.0));
}
return root;
}
#Override
public void onModuleLoad() {
RootPanel.get().add(asWidget());
}
}
There are a handful of issues (no line between locked and unlocked column, locked column header menu context icon is slightly out of place), but it covers most of the details without much hassle, and leaves almost all of it open to configuration - want the lock at the end? Just move the modifications around - want more than one locked column? just add more to the lockedCm.
That functionality is not implemented in GXT, but there is an user called The_Jackal who made a workaround for this problem in the Sencha Forum - Thread. I haven't tried yet, but I hope it can help you.
GXT - Freeze grid workaround Download

User-selected marker in time series data in Java

My code plots 5000 points of time series data in a panel that is 581 pixels wide by default, but this width changes when the user resizes the window. My code also plots several rectangular markers that each identify a local maximum/peak in this same space.
I need to enable the user to right click on any of the rectangular-peak-markers so that the user can manually delete any false peak. The problem is that my code is reporting different x-coordinates than expected when the user right-clicks on a peak-marker. I suspect that the reason may have to do with rounding error in converting from 581 x-pixels back to 5000 data indices. But I am not certain of the reason.
Can anyone suggest a solution that enables my users to manually select one of the above-described peak markers by right-clicking on it?
I am enclosing relevant sections of the code below. My actual code is very, very long, and too complicated to post. But the relevant portions below should be enough for someone to see the logic of my approach, and to then suggest a more effective approach.
The code that declares the class in question is:
class SineDraw extends JPanel implements MouseMotionListener, MouseListener {
// lots of code, including the two segments excerpted below
}
This segment of code overloads the paintComponent of the JPanel so that my data is plotted:
// declare some variables
ArrayList<Double> PeakList = new ArrayList<Double>() // this ArrayList is populated by an extraneous process
visiblePoints = 5000
hstep = getWidth()/visiblePoints //=581/5000 by default, but will change when user resizes window
int numPeaks = PeakList.size();
// scale (y-coordinate) data relative to height of panel
pts = new double[visiblePoints]
for (int i = 0; i < pts.length-1; i++){pts[i]=//data vertical scaled to fill panel;}
// plot the 5000 time-series-data-points within the 581 pixels in x-axis
for (int i = 1; i < visiblePoints; i++) {
int x1 = (int) ((i - 1) * hstep);
int x2 = (int) (i * hstep);
int y1 = (int)pts[i - 1];
int y2 = (int)pts[i];
g2.drawLine(x1, y1, x2, y2);
}
// plot a rectangle for each of the local peaks
for(int m=0;m<=(numPeaks-1);m++){
if(i==(int)(PeakList.get(m)){
int currentVal = (int)pts[(int)(PeakList.get(m)];
g2.drawRect((int)(PeakList.get(m), currentVal, 6, 6);
}
}
This section of code is for handling the right-clicking of the mouse:
public void mousePressed(MouseEvent e){
// check to see if right mouse button was clicked
boolean jones = (e.getModifiers()&InputEvent.BUTTON3_MASK)==InputEvent.BUTTON3_MASK;
if(jones==true){
// test the value returned as x-coordinate when user right-clicks (code always underestimates x-coordinate of local peaks by this test)
double ReverseHstep = visiblePoints/getWidth();
int getX_ConvertedTo_i = (int) (e.getX()*ReverseHstep);
System.out.println("getX_ConvertedTo_i is: "+getX_ConvertedTo_i );
// check to see if peaklist contains a value within the x-coordinates of the user-selected-rectangle
if(PeakList.contains((double)(e.getX()-3))
||PeakList.contains((double)(e.getX()-2))
||PeakList.contains((double)(e.getX()-1))
||PeakList.contains((double)(e.getX()))
||PeakList.contains((double)(e.getX()+1))
||PeakList.contains((double)(e.getX()+2))
||PeakList.contains((double)(e.getX()+3))
){
// handling code will go here, but for now it is a print test that never succeeds because x-coordinate is always underestimated
System.out.println("You just selected a peak!");
}
}
repaint();
}
I suggest you create objects (in this case Rectangles) for each thing you want to be clickable. Here is an over-simplified example of how you can make something you draw clickable. The key thing to take away from this is the mouseClicked method which will display a dialog only if the mouse clicked within the rectangle.
One tricky point is that I wasn't able to figure out how to make the rectangle filled in with color without drawing another rectangle over it. I'll leave that one for you ;-)
public class Canvas extends JPanel implements MouseListener{
private Rectangle rect = new Rectangle(100,100);
public Canvas(){
this.addMouseListener(this);
rect.setSize(100, 100);
}
#Override
public void paintComponent(Graphics g){
g.setClip(rect);
g.setColor(Color.RED);
g.fillRect(0, 0, 100, 100);
}
#Override
public void mouseClicked(MouseEvent e){
if(rect.contains(e.getPoint())){
JOptionPane.showConfirmDialog(this, "Click!");
}
}
// The rest of the MouseListener methods have been cut out
public static void main(String[] a){
JFrame frame = new JFrame("Canvas Thingy");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(0, 0, 300, 300);
frame.add(new Canvas());
frame.setVisible(true);
}
}

Categories