I'm writing a simple application with 2 dialogs, the first for one original image, which is sent to another dialog and processed. Then the image processed is sent back to the first dialog:
ImageDialog::ImageDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ImageDialog)
{
ui->setupUi(this);
ui->graphicsView->setScene(&mScene);
mPixmapItem = new QGraphicsPixmapItem();
connect( this, SIGNAL( sigCommitImage(QImage) ),
parent, SLOT( updateImage(QImage) ) );
}
ImageDialog::~ImageDialog()
{
delete ui;
delete mPixmapItem;
}
void ImageDialog::processImage(const QImage &image )
{
cv::Mat tmp(image.height(),image.width(),CV_8UC4,(uchar*)image.bits(),image.bytesPerLine());
cv::cvtColor(tmp, tmp, CV_RGBA2GRAY);
mImage = QImage( (uchar*)tmp.data, tmp.cols, tmp.rows, tmp.step, QImage::Format_Indexed8 );
mPixmapItem->setPixmap(QPixmap::fromImage(mImage));
mScene.clear();
mScene.addPixmap(QPixmap::fromImage(mImage));
mScene.setSceneRect(0, 0, mImage.width(), mImage.height());
ui->graphicsView->fitInView(mPixmapItem, Qt::KeepAspectRatio);
}
void ImageDialog::on_buttonBox_accepted()
{
emit( sigCommitImage( mImage ) );
}
and there's a snippet for the main window
mPixelInfoDialog = new PixelInfoDialog( this );
connect( this, SIGNAL( sigPixelInfoDialog(QPixmap, QPointF) ),
mPixelInfoDialog, SLOT( updateClip(QPixmap, QPointF) ) );
mImageDialog = new ImageDialog( this );
connect( this, SIGNAL( sigImageDialog(QImage) ),
mImageDialog, SLOT( processImage(QImage) ) );
void MainWindow::updateImage(const QImage &image)
{
showImage( image );
}
void MainWindow::showImage(const QImage &image)
{
mImage = image;
mPixmapItem->setPixmap(QPixmap::fromImage(image));
mScene.clear();
mScene.addPixmap(QPixmap::fromImage(image));
mScene.setSceneRect(0, 0, image.width(), image.height());
ui->graphicsView->fitInView(mPixmapItem, Qt::KeepAspectRatio);
}
void MainWindow::on_action_Open_triggered()
{
QString path = QFileDialog::getOpenFileName();
if( path.isEmpty() )
{
return;
}
QImage image(path);
if( image.isNull() )
return;
showImage( image );
/*
* Update other open dialogs
*/
if( mImageDialog->isEnabled() )
{
emit( sigImageDialog( mImage ) );
}
}
The image is properly loaded, sent to ImageDialog and processed, but when I try to send back the image, the result is a bunch of random pixel or the application crash in
mPixmapItem->setPixmap(QPixmap::fromImage(image));
I can't figure what's happening because I'm doing the same operations.
Any advice?
Thanks in advance
Related
I am sending myself UDP packets generally using this method here:
How to receive proper UDP packet in QT?
I am setting up modes so that in Write mode, it sends UDP packets every second, and in Read mode, it just receives packets. To do this I set up a simple boolean variable called readmode when readmode = true it reads and writes when = false. I left the connect(socket, SIGNAL(readyRead()), this,SLOT(readyRead())); and the call to the send function in the MainWindow constructor and put the if statements, testing the state of readMode to actually do something, in the send function and readyRead() function themselves.
My problem is that I only receive packets whenever I start the program in Read mode first before opening the window for the program to write. If I start sending packets before I open the Read program, I get nothing.
For clarification I am opening two instances of this program and I set one to Read and the other to Write, but the Read has to be started first for it to work, but once states are changed, it stops working.
How can I get it to read all the time?
Code sample:
bool readMode = true; //Write mode = false, Read Mode = true
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
timer = new QTimer(this);
timer->start(1000);
ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Read");
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText("Write");
out_socket = new QUdpSocket(this);
out_socket->bind(60500);
in_socket = new QUdpSocket(this);
in_socket->bind(60510);
connect(timer, SIGNAL(timeout()),this,SLOT(UDP_test()));
connect(in_socket,SIGNAL(readyRead()),this,SLOT(readyRead()));
}
void MainWindow::UDP_test() //Write Mode
{
if (readMode == false) //Write Mode
{
QByteArray Data;
Data.append(fullResultString);
out_socket->writeDatagram(Data,QHostAddress("192.168.127.10"),60510);
}
void MainWindow::readyRead() //Read Mode
{
if (readMode == true) //Readmode
{
while(in_socket->hasPendingDatagrams())
{
QByteArray UDPBuffer;
UDPBuffer.resize(in_socket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
in_socket->readDatagram(UDPBuffer.data(),UDPBuffer.size(), &sender, &senderPort);
}
That's to be expected: each invocation of the process attempts to bind the input socket. The first time, with the socket not bound yet - it succeeds. The second time - it fails, as the port is already bound - so reading won't work. Everything aside, the code never checks for errors, and thus leaves the user (i.e. you) unaware that things have failed. With error checking it'd be obvious why it doesn't work. The output socket doesn't need to be bound to an explicitly specified port number. The input socket should only be bound when the program is in receive mode.
QUdpSocket doesn't emit readyRead if it already contains (not read) datagramms when it receives a new datagram. You source code doesn't complete. So we can't see how do you change your global variable 'readMode'.
here the simple demo application:
#include <QApplication>
#include <QWidget>
#include <QUdpSocket>
#include <QPushButton>
#include <QListWidget>
#include <QGridLayout>
#include <QDebug>
#include <QUuid>
int main( int argc, char** argv ) {
QApplication app( argc, argv );
QWidget form;
auto*const log_widget = new QListWidget( &form );
auto*const client = new QUdpSocket( qApp );
auto*const server = new QUdpSocket( qApp );
const quint16 TEST_PORT = 31088;
if( ! server->bind( QHostAddress::LocalHost, TEST_PORT ) ) {
exit( 1 );
}
QObject::connect( server, &QUdpSocket::readyRead, [=]() {
log_widget->insertItem( 0, "readyRead() has been received" );
});
auto*const write_button = new QPushButton( "&Write", &form );
QObject::connect( write_button, &QPushButton::clicked, [=]() {
const auto packet = QUuid::createUuid().toByteArray();
client->writeDatagram( packet, QHostAddress::LocalHost, TEST_PORT );
log_widget->insertItem( 0, "A datagram has been sent." );
});
auto*const read_button = new QPushButton( "&Read", &form );
QObject::connect( read_button, &QPushButton::clicked, [=]() {
if( server->hasPendingDatagrams() ) {
const int size = static_cast< int >( server->pendingDatagramSize() );
if( size > 0 ) {
QByteArray packet;
packet.resize( size );
server->readDatagram( packet.data(), size );
log_widget->insertItem( 0, "Read OK: datagram have been read." );
} else {
log_widget->insertItem( 0, "Read Error: invalid datagram size." );
}
} else {
log_widget->insertItem( 0, "Read Error: there is no any datagram." );
}
});
auto*const check_button = new QPushButton( "&Check", &form );
QObject::connect( check_button, &QPushButton::clicked, [=]() {
if( server->hasPendingDatagrams() ) {
log_widget->insertItem( 0, "Check: there is at least one datagram." );
} else {
log_widget->insertItem( 0, "Check: there is no any datagram." );
}
});
auto*const grid = new QGridLayout( &form );
grid->addWidget( write_button, 0, 0 );
grid->addWidget( read_button, 0, 1 );
grid->addWidget( check_button, 0, 2 );
grid->addWidget( log_widget, 1, 0, 1, 3 );
form.show();
return app.exec();
}
I know this question has been asked few times but all suggestions given there doesn't work for me.
Overview: I am implementing client server model and wants that as soon as msg arrived in server it should get displayed in main Qt widget. the widget , I choose to display msg is QLineEdit.
I have 3 files in project at the moment. Agent_A which is has all widget created dynamically. Then Server_test based on QTCPServer and sockClient for socket connection. I have received message on sockclient successfully from client but I don't know how to display it correctly on Agent_A .
I have added function in socketClient.cpp to update function in Agent_A but I guess when creating instance it always being NULL.
First a small snippet of my code and then what I have tried. may be you guys can input some valuable info.
Agent_A.h
class Agent_A : public QWidget
{
Q_OBJECT
public:
explicit Agent_A(QWidget *parent = 0);
void setLineEdit( const& modifyStr ); // function to change lineEditCmdString
~Agent_A();
private:
Ui::Agent_A *ui;
QPushButton *buttonStartServer;
QPushButton *buttonStopServer;
// some other widgets
QLabel *labelDisplay;
QLineEdit *lineEditCmdString;// I want to modify this value from sock client
ServerTest *server;
// few slots defined here
}
Agent_A.cpp
Agent_A::Agent_A( QWidget *parent ):
QWidget( parent ),
ui( new Ui::Agent_A )
{
//define push buttons
buttonStartServer = new QPushButton( tr( "&Start Server" ) );
buttonStopServer = new QPushButton( tr( "S&top" ));
// some properties of other widgets defined here which is not relevant to mention here
labelDisplay = new QLabel( tr("DisplayMessgae" ) );
lineEditCmdString = new QLineEdit;// I want to modify this value on sock client
labelDisplay->setBuddy( lineEditCmdString );
// define signals and slots for Server
connect( buttonStartServer, SIGNAL( clicked() ), this, SLOT( startServers() ) );
connect( buttonStopServer, SIGNAL( clicked() ), this, SLOT( stopServer() ) );
// some layout here which agian is not important to mention here.
ui->setupUi( this );
}
Agent_A::~Agent_A()
{
delete ui;
}
void Agent_A::setLineEdit( const Qstring& modifyStr )
{
lineEditCmdString->setText( modifyStr );
}
// now by socket client which creates socket
sockClient.h
class SockClient : public QObject
{
Q_OBJECT
public:
explicit SockClient( QObject *parent, QTcpSocket* socket= 0 );
~SockClient();
// I have added this function to update QLIneEdit in Agent_A
void updateTextinParent(const QString &changeText);
signals:
private slots:
void readClient();
private:
// some other functions
QTcpSocket *socketClient;
quint16 nextBlockSize;
public slots:
};
sockclient.cpp
// constructor for sockclient and some other functions
SockClient::SockClient( QObject *parent, QTcpSocket* socket ) : QObject( parent )
{
socketClient = socket ;
// create signals and slots
connect( socketClient, SIGNAL( readyRead() ), this, SLOT( readClient() ) );
connect( socketClient, SIGNAL( disconnected() ), this, SLOT( deleteLater() ) );
}
SockClient::~SockClient()
{
socketClient->close();
delete socketClient;
}
void SockClient::readClient()
{
QDataStream clientReadStream( socketClient );
clientReadStream.setVersion( QDataStream::Qt_4_3 );
QString strRecvFrm;
quint8 requestType;
clientReadStream >> nextBlockSize;
clientReadStream >> requestType;
if( requestType == 'S')
{
clientReadStream >> strRecvFrm;
}
qDebug() << " the string is " << strRecvFrm; // Has recieved correctly from client
updateTextinParent( strRecvFrmMops ); // Now trying to update widget
socketClient->close();
}
void SockClient::updateTextinParent( const QString& changeText )
{
if( this->parent() == 0 )
{
qDebug() << " Parent not assigned"; // This get printed ..
}
Agent_A *agent = qobject_cast< Agent_A* >( this->parent() ); // ?? is this is right way to do..?
if( agent != NULL )
{
qDebug() << " we are in updateTextin" << changeText; // it never get printed so I assume instance is always nULL
agent->setLineEdit( changeText );
}
}
// ServerTest.cpp where instance of sockClient is created
ServerTest::ServerTest(QObject *parent) : QObject(parent)
{
server = new QTcpServer( this );
}
void ServerTest::startServer()
{
connect( server, SIGNAL( newConnection() ), this, SLOT( incomingConnection() ) );
if( !server->listen( QHostAddress::Any, 9999) )
{
qDebug() << " Server failed to get started";
}
else
{
qDebug() << " Server started";
}
}
void ServerTest::stopServer()
{
server->close();
qDebug() << "Server closed";
}
ServerTest::~ServerTest()
{
server->close();
delete socketforClient;
delete server;
}
void ServerTest::incomingConnection()
{
socketforClient = new SockClient(this->parent(), server->nextPendingConnection() );
}
This is a very simple example:
qt.pro:
TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .
# Input
HEADERS += classes.h
SOURCES += main.cpp
classes.h:
#include <QObject>
#include <QDebug>
class Agent_A : public QObject
{
Q_OBJECT
public slots:
void updateText(const QString &changeText) {
qDebug() << "updateText: " << changeText;
};
};
class SockClient : public QObject
{
Q_OBJECT
signals:
void updateTextinParent(const QString &text);
public:
void incomingText(const QString &text) {
emit updateTextinParent(text);
};
};
main.cpp:
#include "classes.h"
int main(int argc, char **argv) {
Agent_A *agent = new Agent_A;
SockClient client;
QObject::connect(&client, SIGNAL(updateTextinParent(const QString &)),
agent, SLOT(updateText(const QString &)));
client.incomingText(QString("hello"));
return 0;
}
Agent_A *agent = qobject_cast< Agent_A* >( this->parent() ); // ?? is this is right way to do..?
if( agent != NULL )
{
qDebug() << " we are in updateTextin" << changeText; // it never get printed so I assume instance is always nULL
agent->setLineEdit( chnageText );
}
Could you please check first that parent is not NULL?
And could you please show code where you create instance of SockClient?
Of course, you can't modify text because of you set as parent to socketClient object this pointer in Server_test class, so parent to socketClient will be Server_test but no Agent_A.
So make parent Agent_A for socketClient object:
socketforClient = new SockClient(this->parent(), server->nextPendingConnection());
Or you can make some others workarounds.
One more note: you make connection to newConnection() signal at your startServer method, not constructor. So if i start server, then stop them and start again server will be connected twice to signal and slot incomingConnection() will be called twice too. So you need disconnect at from signal at stopServer() method or do connection at constructor of class or use Qt::UniqueConnection.
My situation: I have a grid layout with n*n widgets inside. Additionally I place an overlay widget in the grid with position 0,0 and span n,n.
Evertyhing fine with this, but there is a weird margin and I don't know what causes it...
Has anyone an idea how i can prevent this? I think I'm missing something trivial...
SudokuFieldWidget::SudokuFieldWidget(QWidget *parent) : QFrame(parent)
{
...
m_layout = new QGridLayout( this );
m_layout->setSpacing( 0 );
m_layout->setMargin( 1 );
this->initCells( true );
this->setLayout( m_layout );
m_markerOverlay = new SudokuMarkerOverlayWidget( this );
m_layout->addWidget( m_markerOverlay, 0, 0, m_fieldSize, m_fieldSize );
}
SudokuMarkerOverlayWidget::SudokuMarkerOverlayWidget(QWidget* parent) : QWidget(parent)
{
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
...
}
void SudokuMarkerOverlayWidget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
painter.fillRect( rect(), QColor( 255, 0, 0, 128 ) );
}
Had an error in my paint-Routine for SudokuFieldWidget which caused this misbehaviour... m_markerOverlay->setGeometry( this->geometry() );
I have a mainWindow and a Dialog in Qt . I am opening two images in MainWindow . After I make operations with image (crop, resize, rotate ) on MainWindow . I want to send images to another window (QDialog) . How can i send it as a parameter? My partial code is below ;
MainWindow::MainWindow()
{
openButton_1 = new QPushButton(tr("Open"));
cropButton_1 = new QPushButton(tr("Crop"));
rotateButton_1 = new QPushButton(tr("Rotate"));
resizeButton_1 = new QPushButton(tr("Resize"));
doneButton = new QPushButton(tr("Done"));
....
....
....
....
....
connect(openButton_1, SIGNAL(clicked()), this, SLOT(open1()));
connect(openButton_2, SIGNAL(clicked()), this, SLOT(open2()));
connect(doneButton, SIGNAL(clicked()), this, SLOT(done()));
// done() function for open new Window
void MainWindow::done()
{
CompareImage dialog(this);
dialog.exec();
}
// new dialog window
CompareImage::CompareImage( QWidget *parent ) : QDialog( parent )
{
pushButton = new QPushButton(tr("TesT"));
graphicsScene = new QGraphicsScene;
graphicsView = new QGraphicsView(graphicsScene);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget( pushButton );
mainLayout->addWidget( graphicsView );
setLayout( mainLayout );
}
// And here also my open() function
void MainWindow::open( int signal )
{
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open File"), QDir::currentPath());
if (!fileName.isEmpty()) {
QImage image(fileName);
if (image.isNull()) {
QMessageBox::information(this, tr("Image Viewer"),
tr("Cannot load %1.").arg(fileName));
return;
}
QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(image));
if( signal == 1 )
{
graphicsScene_1->addItem(item);
graphicsView_1->show();
}
else if(signal == 2)
{
graphicsScene_2->addItem(item);
graphicsView_2->show();
}
}
}
It looks good idea to use QGraphicsPixmapItem* item but i couldnt make it .. Could you help me? Thanks for ideas..
> EDİT: here also my open1 and open2 function to understand situation clearly..
void MainWindow::open1()
{
open( 1 );
}
void MainWindow::open2()
{
open( 2 );
}
The good way to do it will be using signals/slots
1. In main window declaration add smth like:
signals:
void ImageProcessingDone(QImage& image);
2. In your dialog declare slot
public slosts:
void RecevedProcessedImage(QImage& image);
3. Implpement slot for processing image.
4. In constructo of main window connect signal and slot.
So when your image processing will be done just write in MainWindow emit ImageProcessingDone(imageInstance) and it will be transfered to your dialog
I'm trying to learn the Qt framework. My QStateMachine code does the correct thing (pressing the button makes the chat window popup change size).
I can't change the speed of the animation to get a nice visual transition.
Any suggestions?
Here's the code:
MainWindow::MainWindow()
{
widget.setupUi( this );
// chat window - Chat button opens
ChatWindowClosedState = new QState();
ChatWindowOpenState = new QState();
ChatWindowOpenGeometry = widget.groupBox->geometry();
ChatWindowClosedGeometry = widget.pushButton->geometry();
ChatWindowClosedGeometry.translate( -ChatWindowClosedGeometry.width(), 0 );
ChatWindowClosedState->assignProperty( widget.groupBox, "geometry", ChatWindowClosedGeometry );
ChatWindowOpenState->assignProperty( widget.groupBox, "geometry", ChatWindowOpenGeometry );
ChatWindowCloseTransition = ChatWindowClosedState->addTransition( widget.pushButton, SIGNAL( clicked() ), ChatWindowOpenState );
ChatWindowCloseAnimation = new QPropertyAnimation( widget.pushButton, "geometry" );
ChatWindowCloseAnimation->setDuration( 5000 );
ChatWindowCloseTransition->addAnimation( ChatWindowCloseAnimation );
ChatWindowOpenTransition = ChatWindowOpenState->addTransition( widget.pushButton, SIGNAL( clicked() ), ChatWindowClosedState );
ChatWindowOpenAnimation = new QPropertyAnimation( widget.pushButton, "geometry" );
ChatWindowOpenAnimation->setDuration( 5000 );
ChatWindowOpenTransition->addAnimation( ChatWindowOpenAnimation );
machine = new QStateMachine( this );
machine->addState( ChatWindowClosedState );
machine->addState( ChatWindowOpenState );
machine->setInitialState( ChatWindowClosedState );
machine->start();
}
The code
ChatWindowOpenAnimation = new QPropertyAnimation( widget.pushButton, "geometry" );
should be
ChatWindowOpenAnimation = new QPropertyAnimation( widget.groupBox, "geometry" );
The animation was being applied to the wrong widget.