Draw a triangle with a grid inside - swing

I'm attempting to draw a triangle that has a grid inside. Much like graphing paper. I have the grid, and the triangle drawn, but I don't know how to remove the excess grid. The grid currently is drawn in a for loop until it gets to the end of the triangle's length. The problem is, this will draw a box 'grid' on top of the triangle. Can I draw on top of the excess to get rid of it? Should I draw the lines differently or draw multiple triangles inside the large one to simulate a grid? Assistance would be appreciated.
public class TrianglePanel extends JPanel{
final int pixelParameter = 20;
final int HEIGHT = 800, WIDTH = HEIGHT;
public TrianglePanel(){
setPreferredSize(new Dimension(WIDTH,HEIGHT));
setBackground(Color.white);
}
public void paint(Graphics g){
int [] xPoints = {0,WIDTH/2,0};
int [] yPoints = {HEIGHT,HEIGHT,HEIGHT/2};
g.drawPolygon(xPoints, yPoints, 3); // Draws the triangle
for (int i = pixelParameter; i < WIDTH/2; i += pixelParameter){
g.drawLine(i, HEIGHT, i, (HEIGHT/2)); // Draws vertical lines
g.drawLine(0, HEIGHT - i, (WIDTH/2), HEIGHT - i); // Draws horizontal lines
}
}
}

Custom painting is done by overriding the paintComponent() method, not the paint() method.
Don't forget to invoke super.paintComponent() at the start so the background gets painted.
Create a Polygon object. Then you can try using the Graphics.setClip(Shape) method before you attempt to draw the grid lines.

Related

glow effect with ShapeRenderer (libgdx)

I read about glow/particle effecta with sprites, which are working well.
Is there a simple way to create the similar blur effect with simple shaperender functionality like circles ?
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
batch.end();
shapeRenderer.begin(ShapeRenderer.ShapeType.Point);
shapeRenderer.setAutoShapeType(true);
drawCircle();
shapeRenderer.end();
batch.begin();
}
private void drawCircle() {
shapeRenderer.setColor(Color.WHITE);
shapeRenderer.set(ShapeRenderer.ShapeType.Filled);
// apply effect ??
shapeRenderer.circle(10,10,2);
}
You can't use textures with default ShapeRender.
There are several way to do this but the easiest is to use ShapeDrawer library. It adds some "ShapeRenderer like" capabilities to a SpriteBatch and more. see https://github.com/earlygrey/shapedrawer
Yes, you could create a "glow" effect, this could be achieved by drawing using decreasing alpha values past the boundaries.
Firstly, to define the glow-effect parameters, let's determine the maximum boundary of the glowing object, where the glow ends, as being auraSize for the size of the aura.
Next, we need to know the size of the solid portion of the object, the bit that doesn't glow, and let's call this objSize for the size of the object.
To draw this, we can use a simple for loop and some if statements:
private void drawCircle() {
shapeRenderer.set(ShapeRenderer.ShapeType.Filled);
//Draw circles upto the size of aura
for(int radius = 0; radius < auraSize; radius++) {
/*
* Checks if radius fits object size, sets colour to solid white if so
* Interpolates alpha value to 0 based on distance to aura covered by radius otherwise
*/
if(radius <= objSize) {
shapeRenderer.setColor(Color.WHITE);
} else {
shapeRenderer.setColor(new Color(1, 1, 1,
MathUtils.lerp(1, 0, (radius - objSize) / (auraSize / objSize))));
}
//Draws the circle at the current radius
shapeRenderer.circle(10, 10, radius);
}
}

actionscript issue adding shape to container

I don't know how to describe this problem but I will try to be clear enought. I am doing an actionscript exercise where I have a DisplayObjetct Container defined as Sprite, and what I want is to add ramdomizely circles with a random radio length between 50 and 100.
The Container called "gameZoneContainer_sp" has been added to the displaylist in the Main class, and everytime the user change the size of the stage the container set its new values of width and height.
Here is the code of what i am saying:
private function refreshScreen(ev:Event= null ):void{
// Remember: we can know stage dimensions accessing to:
// stage.stageWidth
// stage.stageHeight
//CONSTANTS DEFINITION OF MARGIN
const margen:Number=25;
//LOCAL VARIABLES DEFINITION
var cercleWidth:Number, cercleHeight:Number;
var invaderWidth:Number, invaderHeight:Number;
var containerWidth:Number, containerHeight:Number;
var logoWidth:Number, logoHeight:Number;
//STORING DIMENSIONS
cercleWidth=addCercle_bt.width;
cercleHeight=addCercle_bt.height;
invaderWidth=addInvader_bt.width;
invaderHeight=addInvader_bt.height;
containerWidth=gameZoneContainer_sp.width;
containerHeight=gameZoneContainer_sp.height;
logoWidth=logoUOC_sp.width;
logoHeight=logoUOC_sp.height;
//SET HORIZONTAL POSITION OF THE ELEMENTS
addCercle_bt.x=(stage.stageWidth/2)+margen;
addInvader_bt.x=(stage.stageWidth/2)-(invaderWidth+margen);
gameZoneContainer_sp.x=margen;
logoUOC_sp.x=stage.stageWidth-(logoWidth+margen);
//SET VERTICAL POSITION OF THE ELEMENTS
addCercle_bt.y=stage.stageHeight - (cercleHeight+margen);
addInvader_bt.y=stage.stageHeight-(invaderHeight+margen);
gameZoneContainer_sp.y=logoHeight+margen*2;
logoUOC_sp.y=margen;
//SET DIMENSIONS OF CONTAINER gameZoneContainer_sp
gameZoneContainer_sp.width=stage.stageWidth-(margen*2);
gameZoneContainer_sp.height=stage.stageHeight-(margen*4)-invaderHeight-logoHeight;
}
/* THIS METHOD ADD A CIRCLE TO THE CONTAINER gameZoneContainer_sp */
private function addCercle(ev:MouseEvent):void {
// Create new instance of Cercle
// and add it to gameZoneContainer_sp
//CONSTANT DEFINITIONS
const minRadio:Number=50, maxRadio:Number=100;
//LOCAL VARIABLES DEFINITIONS OF RADIO, COLOR AND CIRCLE
//THE RADIO CHOOSE A RANDOM VALUE BETWEEN 50 AND 100
var radio:Number=minRadio+(maxRadio-minRadio)*Math.random();
var color:uint=Math.random() * 0xFFFFFF;
var cercle:Cercle=new Cercle(color,radio);
//
var minPosX:Number=radio;
var maxPosX:Number=gameZoneContainer_sp.width/2;
var minPosY:Number=radio;
var maxPosY:Number=gameZoneContainer_sp.height-(minPosY);
// SET POSITION OF THE CIRCULE INSIDE THE CONTAINER
cercle.x= minPosX + (maxPosX-(2*minPosX))*Math.random();
cercle.y= minPosY + (maxPosY-(2*minPosY))*Math.random();
cercle.drawCercle();
gameZoneContainer_sp.addChild(cercle);
refreshScreen(ev);
//TRACING RESULTS...
trace ("Added cercle!");
trace ("alto del contenedor: "+gameZoneContainer_sp.height);
trace ("Posicion x: "+cercle.x);
trace ("radio: "+radio);
}
//DEFINITION OF THE CIRCLE CLASS
public class Cercle extends Sprite {
private var _color:uint;
private var _radio:Number;
public function Cercle(color:uint,radio:Number){
super();
/* THE CLASS ACCEPT HEX VALUES.*/
_color= color;
_radio=radio;
init();
}
public function init():void{
drawCercle ();
}
//METHOD TO DRAW A CIRCLE
public function drawCercle():void{
var circle:Shape=new Shape();
circle.graphics.beginFill(_color,1);
circle.graphics.drawCircle(0,0,_radio);
addChild(circle);
}
}
Here is my problem:
When I add a circle it seems to be fine until I change the dimensions of the windows (the scene). Everytime I update the dimensions, the event execute the method refreshScreen from the main class which update the dimensions and positions of all elements in scene, but after that if i add a new circle, it change the container, and that is wrong because what I want is to add the circle IN the container.
Hope is not too long. Please any help would be great!
Thank you in advance!!
************ HERE GOES THE SOLUTION ********************
//METHOD TO ADD A CIRCLE TO THE CONTAINER
private function addCercle(ev:MouseEvent):void {
// Create new instance of Cercle
// and add it to gameZoneContainer_sp
const minRadio:Number=50, maxRadio:Number=100;
var radio:Number=minRadio+(maxRadio-minRadio)*Math.random();
var color:uint=Math.random() * 0xFFFFFF;
// CHANGES///////
// gameZoneContainer_sp IS 400X400 ORIGINALLY AND WE WANT TO PUT AN INSTANCE OF CIRCLE OBJETCT
// cercle.x WILL PLACE IN minPosX = radio y maxPosy = 400 - radio
// TAKING INTO ACCOUNT THAT ITS RADIO IS cercle.width/2
// cercle.x WILL PLACE IN minPosX = cercle.width/2 y maxPosy = 400 - cercle.width/2
// (SAME FOR y)
var cercle:Cercle=new Cercle(color,radio);
// Cercle scale correction
//cercle.width= radio/(gameZoneContainer_sp.width/400);
//cercle.height= radio/(gameZoneContainer_sp.height/400);
// Cercle positionning
cercle.x = cercle.width/2 + ((400-cercle.width)*Math.random());
cercle.y = cercle.height/2 + ((400-cercle.height)*Math.random());
// PROPORTION CORRECTIONS
//cercle.width = (2*radio)*gameZoneContainer_sp.width/400;
//I ADD IT TO THE CONTAINER
gameZoneContainer_sp.addChild(cercle);
trace ("Added cercle!");
trace ("alto del contenedor: "+gameZoneContainer_sp.height);
trace ("Posicion x: "+cercle.x);
trace ("radio: "+radio);
}
This is what I think is going on. You basically have 2 problems.
You're adding circles using math meant to adjust for the position of the game window, but you don't need that if you are adding it to the game window container. This is resulting in circles that are being added too far to the right.
Something about your Air setup is making the screen contents scale to show all the contents resulting in everything shrinking. (If we fix the first problem, this one will become inconsequential).
So instead of:
cercle.x = minPosX ...etc
do:
cercle.x = Math.Random()*gameZoneContainer_sp.width;
Do likewise for the y value.
You see, the local origin point of an objects container will be that objects (0,0) point locally. So the top left corner of this game container will be the cercle's (0,0) point and therefore there is no need to adjust it to the right by the amount that you do using minPosX. This is assuming you have not made your game container offset from the default somehow (i.e. When you created the rectangle, you did so using (0,0,width,height) and not something like (xOffset,yOffset,width,height)).

In libgdx, correct placement of ShapeRenderer begin and end

My question is whether I should place sRenderer.begin(ShapeType.Filled); and sRenderer.end(); outside of Shape? so they're not called for every Shape.draw()
Or is the approach below ok in terms of performance?
Snippet from one of my Shapes ..
private Body body; // initialized elsewhere
private float width = 1.0f;
private float height = 1.0f;
public void draw(ShapeRenderer sRenderer) {
sRenderer.begin(ShapeType.Filled);
sRenderer.setColor(1.0f, 0.0f, 0.0f, 1.0f);
sRenderer.identity();
sRenderer.translate(getBody().getPosition().x, getBody().getPosition().y, 0);
sRenderer.rotate(0.0f, 0.0f, 1.0f, (float) Math.toDegrees(getBody().getAngle()));
sRenderer.rect(-getWidth(), -getHeight(), getWidth() * 2, getHeight() * 2);
sRenderer.end();
}
In my Level class, theres a draw() method called every frame e.g
for (Body body : bodies) {
if (body.getUserData() instanceof Shape){
((Shape) body.getUserData()).draw(getShapeRenderer());
}
}
Each time you call begin(),identity(), translate(), rotate(), or etc., it will trigger a new flush to the GPU the next time you draw something with the shape renderer. So in your case, moving begin() and end() out of the loop won't have a very significant impact.
If this is a bottle neck, you could try calculating your rectangle corners independently from the shape renderer and submitting four lines to the shape renderer, using world space coordinates instead of local coordinates like you're doing now. Then move begin() and end() out of the loop like you suggested and benchmark the difference. I'm not sure which would be faster in your case. This would reduce draw calls but you'd be translating more points on the CPU as well.

Intersecting JLabels inside a JTable

In the below image I am trying to achieve the following.I have a table and lots of labels embossed over table cells.The height of the labels is always equal to the cell height.So if two labels come in the same point one hides the another as shown in the longer rectangles with red rect over blue.Alternatively what I want is to make the height as half and there by show both the rectangles(showing starting and end points of the rectangle since height is of no use I can half the height of the rectangle to accomodate one more in the same cell.)
I have to do this inside a JTable.To attach a label we can create a JLabel object by setting the rectangular bounds and using table.add(label);
image here
Where did you get the idea that you can do table.add(label) and hope that the label be magically painted over the table?
(Same ??? for #dpatch's answer.)
You have to use cell renderer/editor for any custom painting inside table. (Or layered pane/glass pane if it's something floating above table, but it looks like you want the labels in the cells.)
A crude renderer that paints cell (0, 0) as half-height blue on top of full-height red:
table.getColumnModel().getColumn(0).setCellRenderer(new DefaultTableCellRenderer()
{
private int row_ = 0;
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column)
{
row_ = row;
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
public void setUI(LabelUI ui)
{
super.setUI(new BasicLabelUI()
{
public void paint(Graphics g, JComponent c)
{
super.paint(g, c);
if( row_ == 0 )
{
Rectangle r = g.getClipBounds();
g.setColor(Color.RED);
g.fillRect(r.x, r.y, r.width, r.height);
g.setColor(Color.BLUE);
g.fillRect(r.x, r.y + 1, r.width, r.height/2 - 1);
}
}
});
}
});
Check out the following presentation. I think it talks about solution to similar problem
http://developers.sun.com/learning/javaoneonline/2008/pdf/TS-4982.pdf?cid=925395
When you find two labels that need to be in the same cell, create a JPanel with the red and blue labels each taking up half the height of the panel. Then just add the panel to the table.

How to draw dotted gridlayout cell border using swing?

When i am declaring rows and columns to my gridlayout.eg: 3x2 (3 rows and 2 cols).I have to get a skeletal view of these rows and columns.Like a dotted rectangles.How can we achieve this by using swing ?
regards
Mathan
Add a Border to each of your components in the gridlayout.
Subclass a JPanel to draw a grid within paintChildren(). Any components you add to this panel will show this grid. For example:
public class DebugPanel extends JPanel {
#Override
protected void paintChildren(Graphics g) {
super.paintChildren(g);
g.setColor(Color.GRAY);
// dashed stroke
BasicStroke stroke = new BasicStroke(1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 1,new float[]{5},0);
((Graphics2D)g).setStroke(stroke);
drawComponentGrid(this,g);
}
/**
* Drawn vertical and horizontal guides for a containers child
* components
*/
private static void drawComponentGrid(Container c, Graphics g) {
for(int i=0;i<c.getComponentCount();++i) {
Rectangle r = c.getComponent(i).getBounds();
int x = r.x;
// vertical line at left edge of component
g.drawLine(x,0,x,c.getHeight());
x+= r.width;
// vertical line at right edge of component
g.drawLine(x,0,x,c.getHeight());
// horizontal line at top of component
int y = r.y;
g.drawLine(0,y,c.getWidth(),y);
// horizontal line at bottom of component
y+= r.height;
g.drawLine(0,y,c.getWidth(),y);
}
}
}