LINUX.ORG.RU

qTableWidget и фокус


0

0

есть проект на Qt4. пишется в ubuntu 9.10, используя репозиторный Qt 4.5.3. проблема в следующем. в окне есть 2 tableWidget-а. есть общие для обеих таблиц функции. когда вызывается какая-либо из этих функций, должно быть известно какая таблица в данный момент времени в фокусе. вызываю для каждой таблицы table->hasFocus() и все они возвращают false! focusPolicy для всех таблиц WheelFocus. программа эта, собранная в винде, нормально работает. почему в линуксе таблицы не получают фокус, когда с ними работает пользователь? я уже просто не знаю на что и думать..


ок. вот функция общая для таблиц:


int MainWindow::ArithmeticOperation(QString operation) {

if (operation == «add») { valueDialog->setWindowTitle(«Qr49: add»); }
else if (operation == «multiply») { valueDialog->setWindowTitle(«Qr49: multiply»); }
else if (operation == «divide») { valueDialog->setWindowTitle(«Qr49: divide»); }
else if (operation == «equal») { valueDialog->setWindowTitle(«Qr49: equal»); }
else { ShowMessage(tr(«Error»), tr(«ArithmeticOperation: unknown arithmetic operation!»), «error»); return 1; }

if (valueDialog->exec() == QDialog::Accepted) {

QLineEdit *value = valueDialog->findChild<QLineEdit *>(«lineEdit_Value»);

SelectTable();

QTableWidgetSelectionRange selectedRange = table->selectedRanges().first();

double x = 0;
double y = 0;

for (int i=0; i<selectedRange.rowCount(); i++) {
for (int j=0; j<selectedRange.columnCount(); j++) {

x = table->item(selectedRange.topRow()+i, selectedRange.leftColumn()+j)->text().toDouble();
y = value->text().toDouble();

if (operation == «add») { table->item(selectedRange.topRow()+i, selectedRange.leftColumn()+j)->setText(QString::number(x+y)); }
else if (operation == «multiply») { table->item(selectedRange.topRow()+i, selectedRange.leftColumn()+j)->setText(QString::number(x*y)); }
else if (operation == «divide») { table->item(selectedRange.topRow()+i, selectedRange.leftColumn()+j)->setText(QString::number(x/y)); }
else if (operation == «equal») { table->item(selectedRange.topRow()+i, selectedRange.leftColumn()+j)->setText(QString::number(y)); }
}
}
}
return 0;
}


а вот функция выбора таблицы под фокусом:


void MainWindow::SelectTable() {

if (ui->tableWidget_SrcDataEU0->hasFocus()) { table = ui->tableWidget_SrcDataEU0; }
else if (ui->tableWidget_SrcDataEU3->hasFocus()) { table = ui->tableWidget_SrcDataEU3; }
else if (ui->tableWidget_SrcDataPoints->hasFocus()) { table = ui->tableWidget_SrcDataPoints; }
else if (ui->tableWidget_FullLoadCurve->hasFocus()) { table = ui->tableWidget_FullLoadCurve; }
else if (ui->tableWidget_DataForReport85->hasFocus()) { table = ui->tableWidget_DataForReport85; }
else { ShowMessage(tr(«Error»), tr(«No tables in focus!»), «error»); }
}

pa23
() автор топика
Ответ на: комментарий от pa23

Сама функция QWidget::hasFocus() - это QApplication::focusWidget() == this, т.е. если в фокусе ячейка таблицы, то hasFocus() вернёт false.

QWidget::focusWidget() возвращает указатель на последнего потомка (или на сам виджет), побывавшего в фокусе, или 0, если таких не было.

Т.е., по идее, что-то вроде такого должно сработать:

bool tableHasFocus( QTableWidget* table ) {
	return table->focusWidget() ? table->focusWidget()->hasFocus() : false;
}
summatus
()
Ответ на: комментарий от summatus

Т.е., по идее, что-то вроде такого должно сработать

спасибо за разъяснение. исправился. однако ж таблицы все равно фокуса не получают. только и вижу что свое сообщение «No tables in focus!».

bool MainWindow::TableHasFocus(QTableWidget *tbl) {

	return tbl->focusWidget() ? tbl->focusWidget()->hasFocus() : false;
}

void MainWindow::SelectTable() {

	if ( TableHasFocus(ui->tableWidget_SrcDataEU0) ) {
		table = ui->tableWidget_SrcDataEU0;
	}
	else if ( TableHasFocus(ui->tableWidget_SrcDataEU3) ) {
		table = ui->tableWidget_SrcDataEU3;
	}
	else if ( TableHasFocus(ui->tableWidget_SrcDataPoints) ) {
		table = ui->tableWidget_SrcDataPoints;
	}
	else if ( TableHasFocus(ui->tableWidget_FullLoadCurve) ) {
		table = ui->tableWidget_FullLoadCurve;
	}
	else if ( TableHasFocus(ui->tableWidget_DataForReport85) ) {
		table = ui->tableWidget_DataForReport85;
	}
	else {
		ShowMessage(tr("Error"), tr("No tables in focus!"), "error");
	}
}
pa23
() автор топика
Ответ на: комментарий от summatus

да я бы так не сказал. мало того, только что собрал проект в винде и все работает как положено.

pa23
() автор топика
Ответ на: комментарий от summatus

в винде, кстати, Qt 4.6.0. но в ubuntu я сегодня собирал Qt 4.6.0 и свой проект с ним. «фокусы» остались.

pa23
() автор топика
Ответ на: комментарий от summatus

qDebug! как я мог не проверить! qDebug показал что таблицы фокус получают.

QTabBar(0x9ee8860, name = "qt_tabwidget_tabbar") 
QTableWidget(0x9f1a2f0, name = "tableWidget_SrcDataPoints") 
QTableWidget(0x9f1a2f0, name = "tableWidget_SrcDataPoints") 
QTableWidget(0x9f0dfa8, name = "tableWidget_SrcDataEU3") 
QTableWidget(0x9f0dfa8, name = "tableWidget_SrcDataEU3") 
QTableWidget(0x9ee9b40, name = "tableWidget_SrcDataEU0")
это уже хорошо. тогда буду думать над кодом.

спасибо

pa23
() автор топика

Проблема решена. Отловить какой же виджет у нас сейчас в фокусе можно следующим способом.

в конструкторе:

ui->tableWidget_SrcDataEU0->installEventFilter(this);
ui->tableWidget_SrcDataEU3->installEventFilter(this);
ui->tableWidget_SrcDataPoints->installEventFilter(this);
ui->tableWidget_FullLoadCurve->installEventFilter(this);
ui->tableWidget_DataForReport85->installEventFilter(this);

и создаем функцию:

bool MainWindow::eventFilter(QObject *object, QEvent *event) {

	if (event->type() == QEvent::FocusIn) {
		if (object->objectName() == "tableWidget_SrcDataEU0") {
			table = ui->tableWidget_SrcDataEU0;
		}
		else if (object->objectName() == "tableWidget_SrcDataEU3") {
			table = ui->tableWidget_SrcDataEU3;
		}
		else if (object->objectName() == "tableWidget_SrcDataPoints") {
			table = ui->tableWidget_SrcDataPoints;
		}
		else if (object->objectName() == "tableWidget_FullLoadCurve") {
			table = ui->tableWidget_FullLoadCurve;
		}
		else if (object->objectName() == "tableWidget_DataForReport85") {
			table = ui->tableWidget_DataForReport85;
		}
		else {
			ShowMessage(tr("Error"), tr("No tables in focus!"), "error");
		}
	}

	return false;
}

решение найдено здесь http://stackoverflow.com/questions/321656/when-a-qt-widget-gets-focus

еще раз спасибо summatus за участие

pa23
() автор топика
Ответ на: комментарий от pa23

>Отловить какой же виджет у нас сейчас в фокусе можно следующим способом.

Нет. Используя такой фильтр, максимум, что можно узнать - какая из этих таблиц была в фокусе последней. Кстати, сравнивай не названия объектов, а указатели.

if (object == ui->tableWidget_SrcDataEU0) {

summatus
()
Ответ на: комментарий от summatus

согласен, с именами перемудрил :) а что касается фильтра, да, table будет содержать указатель на таблицу последней побывавшую в фокусе. я модифицировал фильтр следующим образом:

bool MainWindow::eventFilter(QObject *object, QEvent *event) {

	if (event->type() == QEvent::FocusIn) {

		ArithmeticOperationIsAvailable(true);

		if (object == ui->tableWidget_SrcDataEU0) {
			table = ui->tableWidget_SrcDataEU0;
		}
		else if (object == ui->tableWidget_SrcDataEU3) {
			table = ui->tableWidget_SrcDataEU3;
		}
		else if (object == ui->tableWidget_SrcDataPoints) {
			table = ui->tableWidget_SrcDataPoints;
		}
		else if (object == ui->tableWidget_FullLoadCurve) {
			table = ui->tableWidget_FullLoadCurve;
		}
		else if (object == ui->tableWidget_DataForReport85) {
			table = ui->tableWidget_DataForReport85;
		}
	}
	else if (event->type() == QEvent::FocusOut) {

		ArithmeticOperationIsAvailable(false);
	}

	return false;
}

т.е. функции общие для таблиц доступны только тогда когда какая-нибудь из них получает фокус. как только переключаемся на другой виджет - функции для работы с таблицами становятся недоступными и данные там мы не испортим.

pa23
() автор топика
Ответ на: комментарий от pa23

>QEvent::FocusOut

Только помни, что если начать редактировать ячейку одной из этих таблиц, то в ней будет создан временный виджет, и твой фильтр сразу получит FocusOut. Т.е. вроде пользователь продолжает работать с одной из таблиц, а ArithmeticOperation уже не available... Правда если у тебя EditTriggers = NoEditTriggers, то это не важно.

summatus
()
Ответ на: комментарий от summatus

да. так и есть. во время редактирования ячейки ArithmeticOperation-ы не доступны. и не нужны, т.к. пользователь, работая с таблицей, или вводит данные или модифицирует их с помощью ArithmeticOperation.

pa23
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.