Ok, I am implementing a flowchart editor in Java. My goal is to provide a possibility to display grid lines on a drawing surface. I partially made it to work:
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
// Scrolling
g2.transform(transformation);
// Step one: draw grid
if(showGrid)
{
// Horizontal grid lines
for(int i = -1; i < getSize().getWidth(); i += 50)
{
g2.drawLine(i, 0, i, (int)getSize().getHeight());
}
// Vertical grid lines
for(int i = -1; i < getSize().getHeight(); i += 50)
{
g2.drawLine(0, i, (int)getSize().getWidth(), i);
}
}
// Step two: draw symbols
// ...
}
The results are like this:
But, if I scroll the diagram down or up, I get this:
As seen, diagram is scrolled, but not the grid. I also tried putting Step one code before g2.transform(transformation) line, but after that, if I scroll, grid lines are not moving.
So, the question is: is there a way to draw grid lines and avoid mentioned behavior? The goal is to scroll grid along with other elements on diagram.
List item
The grid is being scrolled, but the lines do not extend to the new bounds.
The grid is scrolled along with the objects. That's why there's empty space at the bottom of the second diagram. The top of the grid has been scrolled off the top of the panel. The bottom of the grid has been scrolled above the bottom of the panel. The grid lines have moved.
The only problem I see is that the grid lines should always extend to the extents of the visible area. To do this, you need to reverse the transformation for the getWidth and getHeight and then draw the grid lines on all of the multiples of 50 between those values.
Paint the entire diagram and put it into a JScrollPane instead of transforming scroll actions yourself.
Related
What is the most painless way to create an N x N grid in a JavaFX application?
The only requirements I'm looking for is that the size of the grid will always take up the same amount of space, so more squares = smaller squares. I can set colors for the squares, and I can hover over each square individually and be able to show some for each square.
I won't know 'N' until the program runs and parses through some data to figure out how many total squares I need which is when I calculate the smallest NxN grid I can use.
From what I can tell my options are:
GridPane - Using the column constraints and row constraints to generate size and possibly add properties for hovering?
TableView - A lot more options for being able to give each cell data to show when hovered over but still difficult to just add rows and columns to start with.
Rectangles - Just generate and draw each rectangle while calculating the x and y coordinates for each square. This will make it easy to do the colors and hovering but I can't see how resizing would work but I'm ok with having a specific size for my application. I'll also have to calculate the best size to make each square to fill up the grids area.
I'm not necessarily looking for someone to code a solution, but if someone has dealt with this and knows a good way I'd like to hear about it.
Don't stray away from the original ideas. Why are you looking for "painless" ways when all the methods you've given are all viable? Here's one using your rectangles. The GridMaker.SCREEN_SIZE refers to the size of the screen you must have.
public static Pane makeGrid(int n){
double width = GridMaker.SCREEN_SIZE/n;
Pane p = new Pane();
Rectangle [][] rec = new Rectangle [n][n];
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
rec[i][j] = new Rectangle();
rec[i][j].setX(i * width);
rec[i][j].setY(j * width);
rec[i][j].setWidth(width);
rec[i][j].setHeight(width);
rec[i][j].setFill(null);
rec[i][j].setStroke(Color.BLACK);
p.getChildren().add(rec[i][j]);
}
}
return p;
}
Then simply add the mouse listener to the pane if you wish to make it change color.
p.setOnMouseClicked(new EventHandler <MouseEvent> (){
#Override
public void handle(MouseEvent me){
double posX = me.getX();
double posY = me.getY();
int colX = (int)(posX / width);
int colY = (int) (posY / width);
rec[colX][colY].setFill(Color.RED);
}
});
-- Edit
1)
2) For Hover, what kind of hover effects are you looking for? You can add Hover effects onto each rectangles, if you want me to show you how, I can definitely code it for you.
Situation: I have a canvas on an Android game, I have some objects (I will keep it as simple as possible):World(where are storaged all Laser and Block objects), Block and Laser. I can draw all this objects in the canvas.
I would like to 'hide' them behind a black 'background', and then draw a blurry 'transparent' circle, so all objects are hidden behind the black background, except the objects behing the circle.
I have thought about it, but I can't think of an approach to do this.
Images:
This is my actual situation:
This is the expected:
Do something like this:
public void drawBitmapsInCanvas(Canvas c){
c.drawBitmap(block, new Rect(/*coordinates here*/), new Rect(/*More coordinates*/),null);
c.drawBitmap(block2, new Rect(/*coordinates here*/), new Rect(/*More coordinates*/),null);
c.drawBitmap(laser, new Rect(/*coordinates here*/), new Rect(/*More coordinates*/),null);
c.drawColor(Color.BLACK);//this hides everything under your black background.
c.drawBitmap(circle, new Rect(/*coordinates here*/), new Rect(/*More coordinates*/),null);
}
If you want transparency:
Paint paint =new Paint();
paint.setARGB(120,0,0,0); //for the "120" parameter, 0 is completely transparent, 255 is completely opaque.
paint.setAntiAlias(true);
c.drawBitmap(bmp,Rect r,Rect rr, paint);
or if you are trying to change the opacity of individual pixels, the approach is a bit more complicated (I have not tested the code, but you get the gist of it):
public static final Bitmap getNewBitmap(Bitmap bmp, int circleCenterX,
int circleCenterY,int circleRadius){
//CIRCLE COORDINATES ARE THE DISTANCE IN RESPECT OF (0,0) of the bitmap
//, not (0,0) of the canvas itself. The circleRadius is the circle's radius.
Bitmap temp=bmp.copy(Bitmap.Config.ARGB_8888, true);
int[]pixels = new int[temp.getWidth()*temp.getHeight()];
temp.getPixels(pixels,0 ,temp.getWidth(),0,0,temp.getWidth(), temp.getHeight());
int counter=0;
for(int i=0;i<pixels.length;i++){
int alpha=Color.alpha(pixels[i]);
if(alpha!=0&&!((Math.pow(counter/temp.getWidth()-circleCenterY,2.0)+
Math.pow(counter%temp.getWidth()-circleCenterX,2.0))<Math.pow(circleRadius,2.0))){
//if the pixel itself is not completely transparent and the pixel is NOT within range of the circle,
//set the Alpha value of the pixel to 0.
pixels[i]=Color.argb(0,Color.red(pixels[i]),Color.green(pixels[i]),Color.blue(pixels[i]));
}
counter++;
}
temp.setPixels(pixels,0, temp.getWidth(),0,0,temp.getWidth(),temp.getHeight());
return temp;
}
and then draw temp.
I'm not completely sure what you are trying to ask, so you may have to modify as necessary.
If you try the second answer of qwertyuiop5040, you will get a ver low - perfomance when you try to apply it to a large image. Let's say a 1000*800 pixels image. Then you will have a loop:
for (int i = 0 ; i < 1000*800; i++)
You could create an image that's a black rectangle with a transparent hole in it. The hole would be the circle that you can see through, and the image would be rendered over the spot you want to be visible. Then, you can draw four black rectangles around the image to cover the rest of the screen.
I used an canvas to draw multiple textures on it. these textures are rectangles and now I want to use these textures with parts of them invisble, so I could draw background colors behind the textures to have teh same texture with different colors without adding the same picture with different colors.
I tried to add Rects like this:
for(Coordinate c : ch.getVisibleCoords()) {
ShapeDrawable sD = new ShapeDrawable();
Rect r = new Rect(c.getxS(),
c.getyS(),
(sh.getScreenWidth()-c.getxS()-sh.getTSize()),
(sh.getScreenHeight()-c.getyS()-sh.getTSize()));
sD.setBounds(r);
textureColorRects.add(sD);
}
each coordinate represents an texture the xS and yS values are the positions at the screen, for example coordinate 1|1 could have xS=0 | yS=0 and 2|1 xS=48 (48=texturesize) | yS=0. I tried this with ShapeDrawable and Rectangles itself, in the first case it will draw everything the same color expect of one y-line and in the other case it will draw just some buggy shit.
Is there another way to do this or may I didn't understood how to setup those rectangles, I can't figure out how that left, top, right, bottom stuff works.
The rest of the code is here for you so you can see how I draw the ShapeDrawables:
int i = 0;
for(Coordinate c : ch.getVisibleCoords()) {
ShapeDrawable sD = textureColorRects.get(i);
Paint color = new Paint();
color.setColor(c.getLandscape().getType().getColor());
color.setStyle(Paint.Style.FILL);
sD.getPaint().set(color);
sD.draw(canvas);
}
The textureColorRects is a list containing all ShapeDrawables.
Thank you very much for reading.
I found an solution it's a problem other people had too (was just hard to find) it's a bit hard to understand how the Rect works the values for left, top, right and bottom are seen like the beginning and the ed point for example I want a rectangle of the size 16*16 and at the point x=5|y=18 on the screen, so I need to set the right value to x+size (5+16) and the bottom to y+size (18+16). The lft and top can be set to the left upper edge of the rect (start position).
The scenario: I have a UI that contains a JPanel (call it topGrid) with a grid layout in a JFrame at the top level. Within topGrid, I have placed another JPanel (midGrid) with grid layout. Inside midGrid, is another JPanel (bottomGrid) that has a JLabel that I populate with images depending on an array and what their instance is within that array.
The goal: I would like the topGrid to center its view on a specific object found in bottomGrid. (Picture a game that as the player icon moves, the game's grid moves to center on that icon and also when the game is started it is already centered for the user.)
I've considered getting the Point from bottomGrid and trying to pass it over to topGrid but doesn't seem to pull the correct information. The only way i know to find where the player is, is to iterate through all the components and check instances. this would have to be done once for the topGrid and again for midGrid to find the player at bottomGrid. then pass the Point data. Then use setLocation() on the appropriate JPanel minus the distance from the center.
Has anyone else tried this and have a more effective or elegant way to go about it? What other options could I explore?
Thanks for any feedback.
Creating the grid within topGrid's JPanel:
public void createTopGrid()
{
int rows = galaxy.getNumRows();
int columns = galaxy.getNumColumns();
pnlGrid.removeAll();
pnlGrid.setLayout(new GridLayout(rows, columns));
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < columns; col++)
{
Position pos = new Position(galaxy, row, col);
Sector sector = galaxy.getSector(pos);
GalaxySector sectorUI = new GalaxySector(sector);
pnlGrid.add(sectorUI);
}
}
}
Creating the grid within midGrid's JPanel:
public void createOccupantIcons()
{
pnlGridOccupants.removeAll();
Occupant[] occs = sector.getOccupantsAsArray();
for ( Occupant occ : occs )
{
GalaxyOccupant occupant = new GalaxyOccupant(occ, sector);
pnlGridOccupants.add(occupant);
}
}
The Image icons for each occupant in the midGrid are pulled from an IconRep String in the model in the bottomGrid class' JPanel and added into a JLabel as needed in FlowLayout.
For visual reference:
Where green square is topGrid JPanel, red squares are midGrid JPanel, and the black square is the bottomGrid JPanel with the white circle for the player image inside a JLabel. The blue circle represents a viewport the user will see the game through and is where I want the player icon to be centered to. Currently the user can move the grid's using very inelegant buttons in the area around the viewport. That might be sufficient but at the start of the game the player has to move the grid around until they can locate their icon.
You might also look at JScrollNavigator, examined here. It would allow you to navigate on a thumbnail image of your entire world, seen at full size in an adjacent scroll pane.
Off the top of my head, I would store all the references you want to in some kind of model.
You could use this model to update the views based on selection requirements.
This allows the you to centralise the logic for finding and updating the elements without knowing or caring out the other UI elements
I've written Conway's Game Of Life in Java and I want to display it in a browser. I wanted to learn some Canvas, so what is the preferred way to draw a 2D grid and filling each cell in with a color? Thanks.
This will make a grid. It's useful I think for being able to position or determine the coordinates of an element or something, and several other possible handy use cases as well.
var grid = function() {
for (var i = 0; i < canvasWidth || i < canvasHeight; i += 100) { // 100 represents the width in pixels between each line of the grid
// draw horizontal lines
ctx.moveTo(i, 0);
ctx.lineTo(i, canvasHeight);
// draw vertical lines
ctx.moveTo(0, i);
ctx.lineTo(canvasWidth, i);
}
ctx.save();
ctx.strokeStyle = 'hsla(200, 0%, 20%, 0.8)';
ctx.stroke();
ctx.restore();
};
// Call the function
grid()
Hope this helps, and is what you're trying to do too. :)
edit: If you are looking to fill each grid square with a different color, then this function will not work, or could at least be used in combination with another function which creates and fills the squares in a similar way to the function above but cutting the width and height off based on the dimensions of the canvas width and height.