libGDX getColor() method - button

I have a grid of buttons, displayed on a stage. Setting and getting the color of the buttons is behaving strangely.
int X=0;
int Y=0;
buttons[X][Y].setColor(Color.BLUE); //this works, the button displays blue
boolean test = (buttons[X][Y].getColor()==Color.BLUE);
System.out.println(test); //prints 'false' , why???
System.out.println(buttons[X][Y].getColor()); //prints '0000ffff'
System.out.println(Color.BLUE); //prints '0000ffff'
I need to be able to set and get the color of the buttons for the game I'm creating. Does anyone know what is going on and what I could do?

The Color objects are different, but they have the same value. So, the objects may not be == equal but will be .equal() equal. See What is the difference between == vs equals() in Java?

Related

add negative values to the progress bar

I have a realtime value from a sensor:
ui->progressBar_retraction->setValue(aX*100); //aX is realtime value that can take positive or negative values over time
In the above expression, the progress bar shown the instantaneous positive values of aX.
How do I show negative values in a different progress bar ?
◘ Well, if you want to use another QProgressBar, you obviously need another one. Then simply check the sign of aX and update one of the two accordingly :
if(aX < 0){
progress_bar_neg->setValue(qAbs(aX)*100);
progress_bar_pos->setValue(0);
}else{
progress_bar_pos->setValue(aX*100);
progress_bar_neg->setValue(0);
}
Note that if you want one of your QProgressbar to fill from right to left, you can use void setInvertedAppearance(bool invert) to set its invertedAppearance to true.
◘ Another alternative using the same QProgressBar could look like :
ui->progressBar_retraction->setValue(qAbs(aX)*100);
if(aX < 0){/*Set to a colour*/}
else{/*Set to another colour*}
To edit the colour :
QPalette p;
p.setColor(QPalette::Highlight, Qt::red); //Change background colour, here red
ui->progressBar_retraction->setPalette(p);
p.setColor(QPalette::HighlightedText , Qt::black); //Change text colour, here black
ui->progressBar_retraction->setPalette(p);
◘ If you want a bi-directional QProgessBar, it is unfortunately not possible by only calling a method as far as I know (correct me if I am wrong).
What I did was an override of void QProgressBar::paintEvent(QPaintEvent *) to start the drawing of the rectangle from the middle. You then simply fix the range of the QProgressBar with void QProgressBar::setRange(int minimum, int maximum). You may even update the colour to make it a bit simpler to see.

Implementing updatePaintNode causes other QML elements to also draw incorrectly

I have discovered that geometry->setLineWidth(3); in the code below extends to other QML elements and can distort them, even if those other QML elements are "normal" QML elements (with no QQuickItem subclass beneath them). This seems odd to me that you could affect other elements and I wonder if it is a bug? The documentation says that this function should only affect the current element, but that is not my experience. Can anyone weigh in on why geometry->setLineWidth(3); has such unwieldy power?
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data){
QSGGeometry *geometry =
new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2);
geometry->setDrawingMode(GL_LINES);
geometry->setLineWidth(3);
geometry->vertexDataAsPoint2D()[0].set(0, 0);
geometry->vertexDataAsPoint2D()[1].set(width(), height());
QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
material->setColor(QColor(255, 0, 0));
QSGGeometryNode *node = new QSGGeometryNode;
node->setGeometry(geometry);
node->setFlag(QSGNode::OwnsGeometry);
node->setMaterial(material);
node->setFlag(QSGNode::OwnsMaterial);
delete oldNode;
return node;
}
If I omit the line geometry->setLineWidth(3); then the problem goes away.
I think it's a bug, sort of. The implementation in gsgbatchrenderer.cpp looks like this:
if (g->drawingMode() == GL_LINE_STRIP || g->drawingMode() == GL_LINE_LOOP || g->drawingMode() == GL_LINES)
glLineWidth(g->lineWidth());
The gl functions are global on the current OpenGL context so they apply to all drawing commands, and there's nothing that sets glLineWidth back to its previous value. However, any other nodes that also are in GL_LINES mode will also set the line width when it's their turn to render. So I'm guessing the other QML elements must be rendering lines without going through this code and setting the glLineWidth themselves. If I'm right then that's the bug and those other elements need to explicitly set the width.
Can you tell us what type those other 'normal' QML elements are?

How to do a custom range for a QSpinBox

Hi first time posting here. I searched and found how re-implementing the QSpinBox class allows for custom uses. However I am not sure if my needs are addressed in as much as what I found by re-implementing the validate method.
I need a custom range that excludes a zero value in the range of values. The spinner is used for selecting zoom ratio for a loaded image. The initial range at design time is -25 to 10. That range could change depending on the dimensions of the image. Nevertheless, I have to be able to "skip" zero for a desired zoom factor. For example, the range would have to always be going from -1 to 1 or vice-versa.
I assume you're listening to QSpinbox::valueChanged(int i) signal, there you can do something like this:
void zoomImage(int i) {
if (i == 0) {
if (lastValue < 0) //if sliding from negative values
spinBox->setValue(1);
else
spinBox->setValue(-1);
return; //skip processing for 0
}
else
lastValue = i; //save last state to a class variable
//processing...
}
EDIT: int lastValue is used for storing the position of slider before it hits 0 in order to determine if the user slides to negative or positive values
What seems to have worked:
void MainWindow::zoomImage(int ctlValue)
{
if(ctlValue == 0)
{
if(zoomLastValue < 0)
ui->sbScaleImage->stepBy(1);
else
ui->sbScaleImage->stepBy(-1);
}
zoomLastValue = ui->sbScaleImage->value();
}
Apologies if I screwed up the formatting.

How to maintain vertical scroll position in a QTableWidget

This a very simple problem to which I can find no solution:
This is my code:
qint32 pos = ui->twShow->verticalScrollBar()->value();
ui->twShow->blockSignals(true);
//Code for updating the contents QTableWidget twShow, this is done by erasing all cells and adding them again, in case it matters.
ui->twShow->blockSignals(false);
if (pos > 0){
ui->twShow->verticalScrollBar()->setValue(pos);
}
What I want to accomplish is simply to maintain the vertical scroll position. However the setValue function ignores the value pos (I've checked by printing the value before and after the instruction and both times its cero).
I have also tried:
QScrollBar *bar = ui->twShow->verticalScrollBar();
// Same code as before
ui->twShow->setVerticalScrollBar(bar); //This line crashes de program
However the last line crashes the program (which I've checked by commenting it, and it works fine).
Any advice would be greatly appreciated...
Thank you very much
QTableWidget * tw;
int desiredRow;
// before update
desiredRow = tw->row(tw->itemAt(1,1));
...
// update code
...
tw->scrollToItem( tw->item( desiredRow, 0),
QAbstractItemView::EnsureVisible | QAbstractItemView::PositionAtTop );
QAbstractItemView::EnsureVisible = 0.
The 'or' flag converts the result to an integer which is not allowed as parameter of the scrollToItem method. On the other hand enums are not intended to be used as combined flags.

How can you edit a QTableView cell from a QTest unit test?

I'm writing a unit test for a custom Validator in a QTableView using the QTestLib framework. One of the most basic test cases could be described like this:
Double click the table cell in the third column and the fourth row, and append the number '5' to its content.
It is not sufficient to simply change the value in the model or anything, the test case shall perform it like this:
Double Click the table cell to set it into edit mode
Press the [End] key.
Press the [5] key.
Note: This question has an answer on how to set a table cell into edit mode from code, however the unit test shall try to stick to the possibilities of a human user, i.e. Mouse/Keyboard actions.
I've found out the X/Y position of a cell can be retrieved using QTableView::columnViewportPosition( int ) and QTableView::rowViewportPosition( int ).
However, double clicking at the specified location using QTest::mouseDClick(...) neither selects the cell nor sets it into edit mode:
// Retrieve X/Y coordinates of the cell in the third column and the fourth row
int xPos = m_pTableView->columnViewportPosition( 2 );
int yPos = m_pTableView->rowViewportPosition( 3 );
// This does not work
QTest::mouseDClick( m_pTableView, Qt::LeftButton, QPoint( xPos, yPos ) );
How can I implement the test case which I described above, using Mouse/Keyboard actions only?
PS: I am trying this under Windows XP 32 bit and Qt 4.6.1
There are several things to consider when trying to edit in a QTableView through simulated events:
A QTableView does not display its cells directly, it does that using its viewport(). Likewise, the double click event must be sent to the viewport instead of the table view itself.
Now when you do
QTest::mouseDClick( m_pTableView->viewport(), Qt::LeftButton,
NULL, QPoint( xPos, yPos ) );
the cell will be selected, but not in edit mode (unlike a human-initiated double click which instantly puts the cell into edit mode even if the table view did not have focus before). If you add a single click on the same location before the double click, however, it will work!
If you then sent the [End] keypress to the viewport, the cursor would not jump to the end of the table cell content, but instead the last cell in the current row would be selected.
In order to change the table cell content, you must send the event to the current editor widget instead. The easiest way to do that is the usage of QWidget::focusWidget()
QTest::keyClick( m_pTableView->viewport()->focusWidget(), Qt::Key_End );
Note that using it like that can be unsafe though as focusWidget() can return NULL.
With that knowledge, the test case can be programmed as follows:
// Note: The table view must be visible at this point
// Retrieve X/Y coordinates of the cell in the third column and the fourth row
int xPos = m_pTableView->columnViewportPosition( 2 ) + 5;
int yPos = m_pTableView->rowViewportPosition( 3 ) + 10;
// Retrieve the viewport of the table view
QWidget* pViewport = m_pTableView->viewport();
// Double click the table cell to set it into editor mode
// Note: A simple double click did not work, Click->Double Click works, however
QTest::mouseClick ( pViewport, Qt::LeftButton, NULL, QPoint( xPos, yPos ) );
QTest::mouseDClick( pViewport, Qt::LeftButton, NULL, QPoint( xPos, yPos ) );
// Simulate [End] keypress
QTest::keyClick( pViewport->focusWidget(), Qt::Key_End );
// Simulate [5] keypress
QTest::keyClick( pViewport->focusWidget(), Qt::Key_5 );
(Note: if you want to verify this, you can add QTest::qWait( 1000 ) commands after each event)
If you are using the _data() functions as described here, note that you cannot retrieve the focusWidget() at the time of data creation.
I solved this issue by creating a custom interface ITestAction with only a pure virtual "execute()" function. I then added subclasses with a similar constructor as the QTest::mouseClick(...) etc functions. These classes simply call the QTest functions but use either the widget itself or its focus widget as a parameter, dependent on an additional boolean flag.
The _data() slot then stores a QList< ITestAction* > for each data row, and the actual test slot iterates over that list and calls execute() on each item before the validation is performed.

Resources