I am adding a Canvas in a maximized window, and I am setting its height to the height I get from getVisualBounds(), but I think a part of the canvas is actually behind the taskbar.
double canvasWidth = Screen.getPrimary().getVisualBounds().getWidth() * 0.80;
double canvasHeight = Screen.getPrimary().getVisualBounds().getHeight();
canvas = new Canvas(canvasWidth, canvasHeight);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.BLACK);
gc.fillRect(0, 0, canvasWidth, canvasHeight);
gc.setFill(Color.RED);
gc.fillRect(0, canvasHeight-30, canvasWidth, 30);
gc.fillRect(0, 0, canvasWidth, 30);
root.setCenter(canvas);
To make it visible I have added a 30px red bar in the top and bottom of the canvas. You can see that in the bottom only a small part of the bar appears because the rest of it is hidden behind the taskbar.
I am using Windows 10. How can I fix this (without hiding the taskbar)? Is there something else I should be using other than getVisualBounds()?
Or will I have to figure out the size and position of the taskbar manually? If so, how?
Related
I need a QTextEdit widget which height grows or shrinks to the size of the inner content. I didn't find built-in solution and decided to make my own with connections to &QTextEdit::textChanged signals that will update size of the widget at runtime. In the code snippet I flattened my custom component to raw QTextEdit for simplicity. The problem is that calculation via QFontMetrics is inaccurate, a vertical scrollbar appears with only some pixels to scroll
I want to get rid of any vertical scrollbars in these text widgets.
However, I don't need to get rid of horizontal scrollbars and here is the second problem arises. Seemingly, horizontal scrolls occupy space in the viewport of the text widget and its internal height shrinks by the height of the scrollbar itself
void TestWindow::setupUi(QWidget *parent)
{
QVBoxLayout *v_box0 = new QVBoxLayout(parent);
v_box0->setContentsMargins(0, 0, 0, 0);
QVBoxLayout *v_scroll_layout = new QVBoxLayout();
v_scroll_layout->setContentsMargins(0, 0, 0, 0);
v_scroll_layout->setSpacing(0);
v_scroll_layout->setAlignment(::Qt::AlignTop);
QWidget *scroll_content = new QWidget();
scroll_content->setLayout(v_scroll_layout);
QScrollArea *v_scroll = new QScrollArea();
v_scroll->setWidgetResizable(true);
v_scroll->setWidget(scroll_content);
v_box0->addWidget(v_scroll);
QSize size;
QTextEdit *edit0 = new QTextEdit();
edit0->setLineWrapMode(QTextEdit::NoWrap);
edit0->setText("Hello World 1\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11");
edit0->setFont(viewer_font);
size = edit0->fontMetrics().size(0, edit0->document()->toPlainText());
edit0->document()->setDocumentMargin(0);
edit0->setMinimumHeight(size.height());
QTextEdit *edit1 = new QTextEdit();
edit1->setLineWrapMode(QTextEdit::NoWrap);
edit1->setText("New item");
edit1->setFont(viewer_font);
size = edit1->fontMetrics().size(0, edit1->document()->toPlainText());
edit1->document()->setDocumentMargin(0);
edit1->setMinimumHeight(size.height());
v_scroll_layout->addWidget(edit0);
v_scroll_layout->addWidget(edit1);
setFixedHeight(300);
}
I ran into a possible bug in JavaFX, but having short time, I am looking for a workaround.
I have a bunch of windows containing a chart and a toolbar:
public void createGui() {
root = new VBox();
ToolBar toolbar = new ToolBar();
Button btnConfig = new Button(bundle.getString("chartWindow.menu.configure"));
btnConfig.setOnAction(e -> doChartConfig());
toolbar.getItems().addAll(btnConfig);
chartPane = new VBox();
root.getChildren().setAll(toolbar, chartPane);
VBox.setVgrow(chartPane, Priority.ALWAYS);
scene = new Scene(root);
setScene(scene);
updateChart(); // Creates a chart
}
I have to resize them from code. (Tiling the open charts.) The simplified tiling code is:
// bounds is the user available area of the monitors(s)
double windowWidth = bounds.getWidth() / tileRule.columns;
double windowHeight = bounds.getHeight() / tileRule.rows;
int r = 0;
int c = 0;
for (Window w : sel) {
w.setWidth(windowWidth);
w.setHeight(windowHeight);
w.setX(bounds.getMinX() + c * windowWidth);
w.setY(bounds.getMinY() + r * windowHeight);
c++;
if (c >= tileRule.getColumns()) {
c = 0;
r++;
if (r >= tileRule.rows) {
break;
}
}
}
When I do this, the windows are perfectly arranged:
However, as it is visible, some of the windows contents aren't resized with the window (Now, accidentally, they are the last 3, but it is not always the case. Sometimes there are more, and they are not always the last ones.)
It is clearly visible, that the scene is the one that isn't resized with the window.
As soon as I resize the window manually, the controls are layed out well.
I trled a bunch of things to hack this:
Calling the requestLayout method manually
Removing the root element from the scene and adding again
Removing the scene from the stage and adding again
Adding 100 ms delay between the resize operations
binding the root elements width to the window width (minus border size)
None of the above helped. (Yes, not even adding the scene again! It caused the most spectacular result, because the contents are resized to the window size, but with streaching its content.)
Does anyone have any other idea how to hack this bug?
I'm using Java 8u74.
I have to load images:
Image image = new Image(f.toURI().toString(), width, height, true, true);
Since I also have tiffs, I have to load them differently using JAI:
BufferedImage read = ImageIO.read(f);
Image image = SwingFXUtils.toFXImage(read, null);
Now I have an Image object, but it has the wrong size. Image offers no methods to resize the object. How do I resize is so it has the same size as if I would load a jpg or png with the shown line?
Seems like there should be an easier way to do this, but you can try:
BufferedImage read = ImageIO.read(f);
int[] pixels = new int[width * height] ;
PixelGrabber grabber = new PixelGrabber(read.getScaledInstance(width, height, Image.SCALE_SMOOTH),
0, 0, width, height, 0, pixels, width);
grabber.grabPixels();
WritableImage fxImage = new WritableImage(width, height);
PixelWriter pw = fxImage.getPixelWriter();
pw.setPixels(0, 0, width, height, PixelFormat.getIntArgbInstance(), pixels, 0, width);
Now fxImage is a javafx.scene.image.Image that has dimensions width by height.
Be aware that PixelGrabber.grabPixels() is a blocking call, so you will need to handle InterruptedExceptions. For large images you might want to do this in a Task executed on a background thread, so as not to block the FX Application Thread.
How to clear the contents of the ImageView object so that I can use the PixelWriter object to redraw an image?
Thanks
e.g.
ImageView tmpView = new ImageView();
WritableImage writableImage = new WritableImage(width, height);
PixelWriter pixelWriter = writableImage.getPixelWriter();
...
tmpView.setImage(writableImage);
...
//draw the first image
...
//clear the contents of tmpView
//???
//redraw imgView
pixelWriter.setColor(x, y, color);
In the argb color model, 0 represents transparent. Since a new int[n] creates an int array of length n with all values initialized to 0, the following will make all the pixels transparent:
pixelWriter.setPixels(0, 0, width, height, PixelFormat.getIntArgbInstance(),
new int[width*height], 0, width);
If you want all the pixels to be white (for example), then you can fill the array with the appropriate value:
int[] white = new int[width*height];
Arrays.fill(white, 0xffffffff);
pixelWriter.setPixels(0, 0, width, height, PixelFormat.getIntArgbInstance(),
white, 0, width);
Another option is just to create a new WritableImage and set it in the image view.
Without knowing any further details of the original task I'd use a Canvas here instead of an Image/ImageView. With the drawing capabilities of the Canvas you can easily clear the area without having to create possibly huge arrays which have to be filled with color values.
I want to show difference between a trimed clip and non trimed clip in my video editor application, i.e. I want to add a small film image on my thumbnail for a trimed clip. How can I do this?
It would be just to show the difference between an image and a video in our gallery application.
How to add an image on the top of another one in Qt?
Open the QPainter on the bottom image and draw the top image using its drawPixmap()/drawImage() methods.
QPixmap base, overlay; // come from your code
{
QPainter painter(base);
painter.drawPixmap(100, 100, overlay);
}
If your overlay contains an alpha channel (e.g. fancy PNG icon) and your base image does not, you should create a new QPixmap with an alpha channel and draw both images into it:
QPixmap base, overlay; // come from your code
QPixmap result(base.width(), base.height());
result.fill(Qt::transparent); // force alpha channel
{
QPainter painter(&result);
painter.drawPixmap(0, 0, base);
painter.drawPixmap(100, 100, overlay);
}
QPixmaps and QImages can be used interchangeably, although not all combinations give good performance).
If it's just about showing an image above another, then you could also go with this answer.
QGridLayout *layout = new QGridLayout(widget);
Pixmap base, overlay;
QLabel *background = new Label();
background->setPixmap(&base);
QLabel *lOverlay = new QLabel();
lOverlay->setPixmap(&overlay);
//label gets positioned above textBrowser and is an overlay
layout->addWidget(background, 0, 0, Qt::AlignLeft | Qt::AlignTop);
layout->addWidget(lOverlay, 0, 0, Qt::AlignRight | Qt::AlignBottom);
Of course then the QPixbuf of the background doesn't contain the QPixbuf of the overlay-image, but it only appears to do.