I want to keep my QMainWindow always inside of the desktop, so I add the implementation for QMainWindow::moveEvent :
void MainWindow::moveEvent(QMoveEvent *ev)
{
if(ev->pos().x() < 0) setGeometry(0, ev->oldPos().y(), width(), height());
}
But when I move the window to out of desktop left bounding, the app is crashed.
What is wrong with this code? Why it is crashed? Is my solution correct?
//--Update:
I tried with this:
int newx = ev->pos().x(),
newy = ev->pos().y();
if(ev->pos().x() < 0) newx = 0;
if(ev->pos().y() < 0) newy = 0;
move(newx, newy);
It worked without crash but I'm not satisfied because of the moving is not smooth.
This should smoothly help with the upper left corner .. but you'll need to add some more conditions to get it working for all four sides.
posX and posY are member variables.
void MainWindow::moveStep() { // [SLOT]
int movX = 0, movY = 0;
if(posX < 0) movX = 1;
if(posY < 0) movY = 1;
move(posX + movX, posY + movY);
}
void MainWindow::moveEvent(QMoveEvent *ev) {
if(ev->pos().x() < 0 || ev->pos().y() < 0) {
posX = ev->pos().x();
posY = ev->pos().y();
QTimer::singleShot(10, this, SLOT(moveStep()));
}
}
To have it even more elegantly consider using QVariantAnimation with a QRect and setGeometry().
Related
I coded a program on Processing where all the pixels on the screen are scrambled, but around the cursor. The code works by replacing the pixels with a random pixel between 0 and the pixel the loop is currently on. To find that pixel, I used the code (y*width+x)-1. This code, however, is taking pixels from the entire screen. I want the code to instead take the pixels from a 40m square around the mouse coordinates. How can I do this?
import processing.video.*;
Capture video;
void setup() {
size(640, 480);
video = new Capture(this, 640, 480);
video.start();
}
void draw() {
loadPixels();
if (video.available()){
video.read();
video.loadPixels();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
pixels[y*width+x] = video.pixels[y*video.width+(width-x-1)];
// the code should only be applied 20 pixels around the mouse
if (dist(mouseX, mouseY, x, y) < 20){
int d = int(random(0, y*width+x-1));
pixels[y*width+x] = video.pixels[d];
}
}
}
}
updatePixels();
}
You don't need to iterate through all the pixels to only change a few.
Luckily your sketch is the same size as the webcam feed, so you're on the right track using the x + (y + width) arithmetic to convert from a 2D array index to the 1D pixels[] index. Remember that you're sampling from a 1D array currently (random 0, coords). Even if you upate the start/end index that's still a range that will span a few full image rows which means pixels to the left and right of the effect selection. I recommend picking the random x, y indices in 2D, then converting these random values to 1D (as opposed to a single index from the 1D array).
Here's what I mean:
import processing.video.*;
Capture video;
void setup() {
size(640, 480);
video = new Capture(this, 640, 480);
video.start();
}
void draw() {
loadPixels();
if (video.available()) {
video.read();
video.loadPixels();
//for (int y = 0; y < height; y++) {
// for (int x = 0; x < width; x++) {
// pixels[y*width+x] = video.pixels[y*video.width+(width-x-1)];
// // the code should only be applied 20 pixels around the mouse
// if (dist(mouseX, mouseY, x, y) < 20) {
// int d = int(random(0, y*width+x-1));
// pixels[y*width+x] = video.pixels[d];
// }
// }
//}
// mouse x, y shorthand
int mx = mouseX;
int my = mouseY;
// random pixels effect size
int size = 40;
// half of size
int hsize = size / 2;
// 2D pixel coordinates of the effect's bounding box
int minX = mx - hsize;
int maxX = mx + hsize;
int minY = my - hsize;
int maxY = my + hsize;
// apply the effect only where the bounding can be applied
// e.g. avoid a border (of hsize) around edges of the image
if (mx >= hsize && mx < width - hsize &&
my >= hsize && my < height - hsize) {
for(int y = minY; y < maxY; y++){
for(int x = minX; x < maxX; x++){
// pick random x,y coordinates to sample a pixel from
int rx = (int)random(minX, maxX);
int ry = (int)random(minY, maxY);
// convert the 2D random coordinates to a 1D pixel[] index
int ri = rx + (ry * width);
// replace current pixel with randomly sampled pixel (within effect bbox)
pixels[x + (y * width)] = video.pixels[ri];
}
}
}
}
updatePixels();
}
(Note that the above isn't tested, but hopefully the point gets across)
I have a program which visualizes several Images through an ImageView , which are Fit to a size of 55x55 pixels up from around 32x32 pixels.
Unfortunately, all images have a "border" of transparent background, so the images are displayed with a gap inbetween.
Is there a way to crop an Image in javaFX so that it gets reduced to the actual picture?
Example:
desired look (Badly cropped out by hand)
actual look
Afaik there is no build in method for this. As #Slaw mentioned in his comment, you need to use the PixelReader to check for empty rows/columns. Based on that info you can set the viewport property for the ImageView:
#Override
public void start(Stage primaryStage) {
// using stackoverflow logo, since your image is completely opaque
Image image = new Image("https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.png");
ImageView imageView = new ImageView(image);
int w = (int) image.getWidth();
int h = (int) image.getHeight();
int firstNonEmptyColumn = 0;
int firstNonEmptyRow = 0;
int lastNonEmptyColumn = w - 1;
int lastNonEmptyRow = h - 1;
PixelReader reader = image.getPixelReader();
outer: for (; firstNonEmptyColumn < w; firstNonEmptyColumn++) {
for (int y = 0; y < h; y++) {
// stop, if most significant byte (alpha channel) is != 0
if ((reader.getArgb(firstNonEmptyColumn, y) & 0xFF000000) != 0) {
break outer;
}
}
}
if (firstNonEmptyColumn == w) {
imageView.setImage(null); // image completely transparent
} else {
outer: for (; lastNonEmptyColumn > firstNonEmptyColumn; lastNonEmptyColumn--) {
for (int y = 0; y < h; y++) {
if ((reader.getArgb(lastNonEmptyColumn, y) & 0xFF000000) != 0) {
break outer;
}
}
}
outer: for (; firstNonEmptyRow < h; firstNonEmptyRow++) {
// use info for columns to reduce the amount of pixels that need checking
for (int x = firstNonEmptyColumn; x <= lastNonEmptyColumn; x++) {
if ((reader.getArgb(x, firstNonEmptyRow) & 0xFF000000) != 0) {
break outer;
}
}
}
outer: for (; lastNonEmptyRow > firstNonEmptyRow; lastNonEmptyRow--) {
for (int x = firstNonEmptyColumn; x <= lastNonEmptyColumn; x++) {
if ((reader.getArgb(x, lastNonEmptyRow) & 0xFF000000) != 0) {
break outer;
}
}
}
// set viewport to only show the opaque parts
imageView.setViewport(new Rectangle2D(
firstNonEmptyColumn,
firstNonEmptyRow,
lastNonEmptyColumn - firstNonEmptyColumn + 1,
lastNonEmptyRow - firstNonEmptyRow + 1));
}
// visualize image bounds
Rectangle rect = new Rectangle(imageView.prefWidth(-1), imageView.prefHeight(-1), Color.LIGHTGREEN);
StackPane root = new StackPane(rect, imageView);
root.setStyle("-fx-background-color:blue");
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
help please, at Arduino Uno I receive a signal from the sensor and build a graph using processing 2.2.1, but you need to scale up without losing proportions. My attempts failed, the proportion was crumbling(I tried to multiply the values) Code:
Serial myPort;
int xPos = 1;
int yPos = 100;
float yOld = 0;
float yNew = 0;
float inByte = 0;
int lastS = 0;
PFont f;
void setup () {
size(1200, 500);
println(Serial.list());
myPort = new Serial(this, Serial.list()[0], 9600);
myPort.bufferUntil('\n');
background(0xff);
}
void draw () {
int s = second();
PFont f = createFont("Arial",9,false);
textFont(f,9);
fill(0);
if (s != lastS){
stroke(0xcc, 0xcc, 0xcc);
line(xPos, yPos+10, xPos, yPos+30);
text(s + " Sec.", xPos+5, yPos+30);
lastS = s;
}
}
void mousePressed(){
save(lastS + "-heart.jpg");
}
void serialEvent (Serial myPort) {
String inString = myPort.readStringUntil('\n');
if (inString != null) {
inString = trim(inString);
if (inString.equals("!")) {
stroke(0, 0, 0xff); // blue
inByte = 1023;
} else {
stroke(0xff, 0, 0); //Set stroke to red ( R, G, B)
inByte = float(inString);
}
inByte = map(inByte, 0, 1023, 0, height);
yNew = inByte;
line(xPos-1, yPos-yOld, xPos, yPos-yNew);
yOld = yNew;
if (xPos >= width) {
xPos = 1;
yPos+=200;
if (yPos > height-200){
xPos = 1;
yPos=100;
background(0xff);
}
} else {
xPos++;
}
}
}
There are multiple ways to scale graphics.
A simple method to try is to simply scale() the rendering (drawing coordinate system).
Bare in mind currently the buffer is only cleared when the xPos reaches the right hand side of the screen.
The value from Arduino is mapped to Processing here:
inByte = map(inByte, 0, 1023, 0, height);
yNew = inByte;
you should try to map change height to a different value as you see fit.
This however will scale only the Y value. The x value is incremented here:
xPos++;
you might want to change this increment to a different value that works with the proportion you are trying maintain between x and y.
I have a QTableWidget with some columns and rows and want to add a filter for a particular column.
For that, I've added a QLineEdit in my Window.
I'm already able to filter the rows, when I add only one number in the QLineEdit:
for(int i=0; i<tableWidget->rowCount(); i++)
{
if(!tableWidget->item(i, column)->text().contains(lineEdit->text()))
{
tableWidget->hideRow(i);
}
}
(The slot is connected to the textEdited-Signal of the LineEdit)
What I want to do now:
When I write something like this in the QLineEdit: 10-30; Hide all rows, which doesnt have the number between 10 and 30 (>=10; <=30).
Somebody has an idea, how I can solve this?
This is my decision.
Check if lineEdit text contains two numbers.
QString test = ui->lineEdit->text();
QStringList lst = test.split('-');
if (lst.size() == 2)
Transform they in to integers.
int low = QString(lst[0]).toInt(), high = QString(lst[1]).toInt();
Now let's go to tableWidget and drop in less than or equal to these two numbers.
for (int i = 1; i <= 100; i++) {
int row = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(row);
ui->tableWidget->setItem(row, 0, new QTableWidgetItem(QString::number(i)));
}
connect(ui->lineEdit, &QLineEdit::textChanged, this, [=](const QString &test) {
QStringList lst = test.split('-');
if (lst.size() == 2) {
int low = QString(lst[0]).toInt(), high = QString(lst[1]).toInt();
for (int i = 0; i < ui->tableWidget->rowCount(); i++) {
int temp = ui->tableWidget->item(i, 0)->text().toInt();
if (temp < low || temp > high) {
ui->tableWidget->hideRow(i);
} else {
ui->tableWidget->showRow(i);
}
}
}
});
I have to submit a Breakout clone and I'm struggling with the collision detection of the ball and the bricks. Basically, the collision detection works, but the ball destroys the brick about 10 pixels away from the visual object. I'm checking the bounds of both objects, but I guess the problem is that the ball is a moving object and the brick is a static one.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
brick = brickArray[i][j];
if (brick == null)
continue;
areBricksLeft = true;
Bounds brickBounds = brick.getBoundsInParent();
Bounds ballBounds = ball.getBoundsInParent();
if (brickBounds.intersects(ballBounds) ) {
brick.removeBrickAt(i, j, brick, brickArray, brickPane);
didHitBrick = true;
}
}
}
Thanks for the hint I found the mistake. I replaced my condition with this:
double ballX = ball.getLayoutX() + ball.getRadius();
double ballY = ball.getLayoutY() + ball.getRadius();
if ((ballX <= brickBounds.getMaxX() - 10 && ballX >= brickBounds.getMinX() -10) &&
(ballY <= brickBounds.getMaxY() - 10 && ballY >= brickBounds.getMinY() - 10)) {
brick.removeBrickAt(i, j, brick, brickArray, brickPane);
didHitBrick = true;
}
Now it is possible to adjust the collision by substracting and adding values to the bounds.