Here is part of the code, when sending x=0 and y=0, it places the child item "text" in the (0,0) of the scene not relative to its parent !
void ClassA::putLabel(qreal x, qreal y, QString text, QGraphicsPolygonItem* parent) {
QGraphicsTextItem * io = new QGraphicsTextItem;
io->setParentItem(parent);
io->setPos(x, y);
io->setFlags(QGraphicsItem::ItemIgnoresTransformations);
//io->setHtml("<div style='font-size: 10px; padding: -2px; margin: -2px;'>" + text + "</div>");
io->setFont(QFont("Helvetica", 8));
io->setPlainText(text);
}
Related
How can you change the width of a ScrollBar from a ScrollPane to a certain value of px? I looked at JavaFX 2.1 Change ScrollPane Scrollbar size but simply setting the font size to X px doesn't seem to work properly. I did some tests with big values and the width wasn't what I set it to be (ex: for a value of 50px the ScrollBar had width of 56px, for a value of 88px it had width of 96px, for a value of 40px it had width of 44px, for a value of 30px it had width of 33px, so no relation between then).
I need a solution that works from java code and not from a CSS file as I need to be able to dynamically set the value.
There were other suggestions to use .lookupAll but from what I understand you should avoid using that.
Code for setting width and colors:
scrollPane.setStyle("colorScrollBar: rgba(" + A function that returns RBGA + ");"
+ " colorScrollBarButton: rgba(" + A function that returns RBGA + ");"
+ " -fx-font-size: " + 30 + "px;");
Here is the CSS file I used to change the ScrollBar (to make it transparent, to change the colors and remove some margins):
.scroll-bar {
-fx-background-color: colorScrollBar;
-fx-background-insets: 0;
-fx-padding: 0;
}
.scroll-bar .thumb {
-fx-background-color: colorScrollBarButton;
}
.scroll-bar > .increment-button > .increment-arrow,
.scroll-bar > .decrement-button > .decrement-arrow {
-fx-background-color: colorScrollBarButton;
}
.scroll-bar > .increment-button:hover,
.scroll-bar > .decrement-button:hover {
-fx-background-color: colorScrollBar;
}
.scroll-pane > .viewport {
-fx-background-color: transparent;
}
.scroll-pane {
-fx-background-color: transparent;
-fx-background-insets: 0;
-fx-padding: 0;
}
.scroll-pane:focused {
-fx-background-insets: 0;
-fx-padding: 0;
}
.scroll-pane .corner {
-fx-background-insets: 0;
-fx-padding: 0;
}
This works for me.
private ScrollPane scrollPane;
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
Circle content = new Circle(2000);
scrollPane = new ScrollPane(content);
Slider sizeSldr = new Slider(8, 80, 14);
root.setTop(sizeSldr);
root.setCenter(scrollPane);
sizeSldr.valueProperty().addListener((observable, oldValue, newValue) -> {
setScrollBarWidth(newValue.doubleValue());
});
Scene scene = new Scene(root, 800, 600);
primaryStage.setTitle("ScrollBar Width");
primaryStage.setScene(scene);
primaryStage.show();
}
void setScrollBarWidth(double width) {
scrollPane.setStyle("-fx-font-size: %3.3fpx".formatted(width));
}
public static void main(String[] args) {
launch(args);
}
}
The solution I came with is to create a custom ScrollBar and use that to scroll the ScrollPane. Here is an example how to create one and bind it to the ScrollPane:
ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(paneElements); //The pane that will have the nodes
scrollPane.setLayoutX(20);
scrollPane.setLayoutY(20);
scrollPane.setPrefWidth(stage.getWidth() - 40); //This was my use case, do what you need here
scrollPane.setPrefHeight(stage.getHeight() - 66); //This was my use case, do what you need here
scrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
scrollPane.setVbarPolicy(ScrollBarPolicy.NEVER);
scrollPane.setStyle("colorScrollBar: rgba(" + I am using a function that returns RGBA + ");"
+ " colorScrollBarButton: rgba(" + I am using a function that returns RGBA + ");");
pane.getChildren().add(scrollPane);
ScrollBar scrollBarVertical = new ScrollBar();
scrollBarVertical.setLayoutX(stage.getWidth() - 20)); //Use what you need
scrollBarVertical.setLayoutY(20); //Use what you need
scrollBarVertical.setPrefHeight(stage.getHeight() - 66); //Use what you need
scrollBarVertical.setMinWidth(0); //I set it to 0 because if you need to use low values, it wasn't using values lower then 16 in prefWidth in my case
scrollBarVertical.setPrefWidth(prefWidth * 0.75)); //Use what you need
scrollBarVertical.setOrientation(Orientation.VERTICAL);
scrollBarVertical.setMin(scrollPane.getVmin());
scrollBarVertical.setMax(scrollPane.getVmax());
scrollBarVertical.valueProperty().bindBidirectional(scrollPane.vvalueProperty());
scrollBarVertical.setStyle("colorScrollBar: rgba(" + I am using a function that returns RGBA + ");"
+ " colorScrollBarButton: rgba(" + I am using a function that returns RGBA + ");");
pane.getChildren().add(scrollBarVertical);
Once in the Scene, you can query the ScrollBars using:
ScrollBar vsb = (ScrollBar) scrollPane.queryAccessibleAttribute(
AccessibleAttribute.VERTICAL_SCROLLBAR);
ScrollBar hsb = (ScrollBar) scrollPane.queryAccessibleAttribute(
AccessibleAttribute.HORIZONTAL_SCROLLBAR);
vsb.setPrefWidth(40);
hsb.setPrefHeight(40);
I want to add a colored Widget over the full QStatusBar. I added a QLabel with red background-color but there is a padding around the label, which i can't remove.
what i tried:
setSizeGripEnabled(false)
setStyleSheet("QStatusBar { border: 0px; padding: 0px; margin: 0px; }"
"QStatusBar::item { border: 0px; padding: 0px; margin: 0px; }"
layout()->setContentsMargins(0, 0, 0, 0);
Update: Example Code:
QWidget *w = new QWidget;
QHBoxLayout *layout = new QHBoxLayout;
QStatusBar *statusBar = new QStatusBar;
QLabel *label = new QLabel("Example");
w->setStyleSheet("background-color: green");
label->setStyleSheet("background-color: red");
statusBar->addPermanentWidget(label, 1);
statusBar->layout()->setContentsMargins(0, 0, 0, 0);
statusBar->setSizeGripEnabled(false);
setStatusBar(statusBar);
w->setLayout(layout);
setCentralWidget(w);
}
I think it is not possible without pointer hacking or reimplementing all QStatusBar functionality because QStatusBar implementation based on pimpl idiom, which means some implementation hidden in private headers and borders between QStatusBar widget and children widgets are hardcoded in qstatusbar.cpp
QRect ir = item->w->geometry().adjusted(-2, -1, 2, 1);
...
QStyleOption opt(0);
opt.rect = ir;
...
style()->drawPrimitive(QStyle::PE_FrameStatusBarItem, &opt, &p, item->w);
QStatusBar{
min-height: 20px;
}
use the min-height css property.
On my Windows machine text is displayed to the right of the progress bar.
On my Linux machine text appears in the middle of the progress bar.
If I apply style to progress bar, text appears inside on both systems. How do I get it to appear outside, like in default Windows style?
Here's the simplified version of the code I used to play with progress bars:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
auto widget = new QWidget;
auto layout1 = new QVBoxLayout;
widget->setLayout(layout1);
auto layout2 = new QHBoxLayout;
auto progressBar = new QProgressBar;
auto spinBox = new QDoubleSpinBox;
spinBox->setRange(0,100);
spinBox->setDecimals(1);
spinBox->setSingleStep(1);
progressBar->setRange(0, 10000);
connect(spinBox, qOverload<double>(&QDoubleSpinBox::valueChanged), progressBar,
[spinBox, progressBar]
{
progressBar->setValue(spinBox->value() * 100);
progressBar->repaint();
});
layout2->addWidget(spinBox);
layout2->addWidget(progressBar);
auto textEdit = new QPlainTextEdit;
auto stylesheet = R"(
QProgressBar {
background-color: cyan;
border-radius: 1px;
text-align: right;
}
QProgressBar::chunk {
background-color: magenta;
border-radius: 1px;
}
)";
textEdit->setPlainText(stylesheet);
connect(textEdit, &QPlainTextEdit::textChanged, progressBar,
[textEdit, progressBar]
{
progressBar->setStyleSheet(textEdit->toPlainText());
});
layout1->addLayout(layout2);
layout1->addWidget(textEdit, 1);
setCentralWidget(widget);
}
The solution is to use a margin. If you change the QProgressBar section of your stylesheet to this:
QProgressBar {
background-color: cyan;
border-radius: 1px;
text-align: right;
margin-right: 4em;
}
then the right end of the progress bar will stop short of the text (which is right-aligned), resulting in the effect you are looking for.
Suppose I have the following HTML:
<div>
<canvas class="colorPicker" width="800" height="800"></canvas>
<canvas class="colorPicker" width="800" height="800"></canvas>
</div>
And, this CSS:
div {
display: flex;
width: 100%;
overflow: hidden;
}
div > canvas{
flex-grow: 1;
flex-shrink: 1;
width: 50%;
}
The canvases are not scaled proportionally. They are taller than they are wide. This is visible when I paint circles on the canvas.
(JSFiddle: https://jsfiddle.net/08rckfek/)
Why is this happening?
If I don't use flexbox in the parent div, the canvases are scaled correctly.
Furthermore, it seems weird that I have to specify width: 50% at all. flex-shrink is ignored, even if I specify a basis.
How can I make a row of canvases that automatically scale proportionally based on the width of the parent flexbox?
You need to set align-items as by default its value is stretch
document.addEventListener('DOMContentLoaded', (e) => {
document.querySelectorAll('canvas.colorPicker').forEach((canvas) => {
const ctx = canvas.getContext('2d');
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = Math.min(canvas.width, canvas.height) / 2;
// Base white circle, so middle has a full color
ctx.beginPath();
ctx.arc(centerX, centerY, radius/2, 0, 2*Math.PI, false);
ctx.closePath();
ctx.fillStyle = '#fff';
ctx.fill();
for (let angle=0; angle<=360; angle+=1) {
const startAngle = (angle-2)*Math.PI/180;
const endAngle = angle * Math.PI/180;
ctx.beginPath();
ctx.moveTo(centerX, centerY);
ctx.arc(centerX, centerY, radius, startAngle, endAngle);
ctx.closePath();
const gradient = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, radius);
gradient.addColorStop(0, 'hsl(' + angle + ', 100%, 100%)');
gradient.addColorStop(0.5, 'hsl(' + angle + ', 100%, 50%)');
gradient.addColorStop(1, 'hsl(' + angle + ', 100%, 0%)');
ctx.fillStyle = gradient;
ctx.fill();
}
});
});
div {
display: flex;
width: 100%;
overflow: hidden;
align-items:flex-start;
}
div > canvas{
flex-grow: 1;
flex-shrink: 1;
width: 50%;
}
<div>
<canvas class="colorPicker" width="800" height="800"></canvas>
<canvas class="colorPicker" width="800" height="800"></canvas>
</div>
I want to print rows of "QStandardItemModel". I use this code, It works but table is not beautiful.
I don't know how to adjust row height and I don't know how to set column widths based on the width of cells in the first row of the table.
QPrinter printer;
printer.setPageSize(QPrinter::A4);
printer.setFullPage(true);
QPrintDialog *dlg = new QPrintDialog(&printer,0);
if(dlg->exec() == QDialog::Accepted) {
QPainter painter;
if (painter.begin(&printer)) {
painter.translate(0,0);
int position = 0;
int rowCount=newMyModel->rowCount(QModelIndex());
for(int r=0;r<rowCount;r++)
{
if( position > painter.window().height()-100 )
{
printer.newPage();
position = 0;
painter.resetTransform();
painter.translate(0, 0);
}
QString html="<table style='page-break-after:always' border='1' width='100%' cellpadding =10 style='border-width: 1px;border-style: solid;border-color: #9e9e9e;width:100%'>";
index=newMyModel->index(r, 0);
QVariant prop1=index.data(MyModel::prop1);
QVariant prop2=index.data(MyModel::prop2);
'''
'''
'''
html.append(
"<tr style='background-color:red'>"
"<td style='border-width: 1px;padding:10; border-style: solid; border-color: #9e9e9e;width:16%'>"+prop1.toString()+" </td>"
"<td style='border-width: 1px;padding:10; border-style: solid; border-color: #9e9e9e;width:16%'>"+prop2.toString()+" </td>"
...
...
...);
}
html.append("</table>");
QRect rect = painter.boundingRect(painter.window(),
Qt::AlignJustify | Qt::TextWordWrap,
html);
QTextDocument doc;
doc.setHtml(html);
doc.drawContents(&painter, rect);
painter.drawRect(rect);
painter.translate(0, rect.height());
position += rect.height();
}
painter.end();
}
}