在這裏寫下的關於QSpinBox使用int作爲其數據類型的限制的各種問題。通常人們想要顯示更大的數字。在我的情況下,我希望能夠以十六進制顯示無符號的32位整數。這意味着我希望我的範圍是[0x0,0xFFFFFFFF]。一個普通的QSpinBox可以運行的最大值是0x7FFFFFFF。在這裏回答我自己的問題,我提出的解決方案是通過重新實現相關的顯示和驗證函數,簡單地強制int被視爲無符號整型。帶有Unsigned Int的QSpinBox用於十六進制輸入
回答
結果很簡單,而且效果很好。在這裏共享以防其他人可以從中受益。它有一個32位模式和一個16位模式。
class HexSpinBox : public QSpinBox
{
public:
HexSpinBox(bool only16Bits, QWidget *parent = 0) : QSpinBox(parent), m_only16Bits(only16Bits)
{
setPrefix("0x");
setDisplayIntegerBase(16);
if (only16Bits)
setRange(0, 0xFFFF);
else
setRange(INT_MIN, INT_MAX);
}
unsigned int hexValue() const
{
return u(value());
}
void setHexValue(unsigned int value)
{
setValue(i(value));
}
protected:
QString textFromValue(int value) const
{
return QString::number(u(value), 16).toUpper();
}
int valueFromText(const QString &text) const
{
return i(text.toUInt(0, 16));
}
QValidator::State validate(QString &input, int &pos) const
{
QString copy(input);
if (copy.startsWith("0x"))
copy.remove(0, 2);
pos -= copy.size() - copy.trimmed().size();
copy = copy.trimmed();
if (copy.isEmpty())
return QValidator::Intermediate;
input = QString("0x") + copy.toUpper();
bool okay;
unsigned int val = copy.toUInt(&okay, 16);
if (!okay || (m_only16Bits && val > 0xFFFF))
return QValidator::Invalid;
return QValidator::Acceptable;
}
private:
bool m_only16Bits;
inline unsigned int u(int i) const
{
return *reinterpret_cast<unsigned int *>(&i);
}
inline int i(unsigned int u) const
{
return *reinterpret_cast<int *>(&u);
}
};
你的'reinterpret_cast's違反[嚴格的alasing規則](http://eel.is/c++draft/basic.lval#8)。所以代碼包含UB – yrHeTaTeJlb 2017-10-17 08:02:22
我想出了同樣的問題,但使用PyQt的,所以我無法避免檢查的Qt是用C引擎蓋下做的範圍內。
解決方法是使用QDoulbeSpinbox並將值強制轉換爲textFromValue中的int值。
這裏是我的代碼(這也實現了右鍵菜單更改顯示基座):
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from future_builtins import *
import re
import sys
from PyQt4.QtCore import (QRegExp, Qt)
from PyQt4.QtGui import (QApplication, QRegExpValidator, QDoubleSpinBox)
from PyQt4.QtCore import pyqtSlot,SIGNAL,SLOT
from PyQt4 import QtCore, QtGui
# Regex adapted from Mark Pilgrim's "Dive Into Python" book
class QHexSpinBox(QDoubleSpinBox):
def __init__(self, parent=None):
super(QHexSpinBox, self).__init__(parent)
self.mode = 'dec'
self.setContextMenuPolicy(Qt.CustomContextMenu);
regex = QRegExp("[x0-9A-Fa-f]{1,8}")
regex.setCaseSensitivity(Qt.CaseInsensitive)
self.hexvalidator = QRegExpValidator(regex, self)
regex = QRegExp("[0-9]{1,10}")
regex.setCaseSensitivity(Qt.CaseInsensitive)
self.decvalidator = QRegExpValidator(regex, self)
regex = QRegExp("[b0-1]{1,64}")
regex.setCaseSensitivity(Qt.CaseInsensitive)
self.binvalidator = QRegExpValidator(regex, self)
self.setRange(1, 999999)
self.connect(self,SIGNAL("customContextMenuRequested(QPoint)"),
self,SLOT("contextMenuRequested(QPoint)"))
@pyqtSlot(QtCore.QPoint)
def contextMenuRequested(self,point):
menu = QtGui.QMenu()
hex = menu.addAction("Hex")
dec = menu.addAction("Dec")
bin = menu.addAction("Bin")
self.connect(hex,SIGNAL("triggered()"),
self,SLOT("hex()"))
self.connect(dec,SIGNAL("triggered()"),
self,SLOT("dec()"))
self.connect(bin,SIGNAL("triggered()"),
self,SLOT("bin()"))
menu.exec_(self.mapToGlobal(point))
@pyqtSlot()
def hex(self):
self.mode = 'hex'
self.setValue(self.value())
@pyqtSlot()
def dec(self):
self.mode = 'dec'
self.setValue(self.value())
@pyqtSlot()
def bin(self):
self.mode = 'bin'
self.setValue(self.value())
def validate(self, text, pos):
if self.mode == 'hex':
return self.hexvalidator.validate(text, pos)
if self.mode == 'dec':
return self.decvalidator.validate(text, pos)
if self.mode == 'bin':
return self.binvalidator.validate(text, pos)
def valueFromText(self, text):
if self.mode == 'hex':
return int(unicode(text), 16)
elif self.mode == 'dec':
return int(unicode(text))
elif self.mode == 'bin':
return int(unicode(text), 2)
def textFromValue(self, value):
value = int(value)
if self.mode == 'hex':
return hex(value)
elif self.mode == 'dec':
return str(value)
elif self.mode =='bin':
return "0b{0:b}".format(value)
有趣的「方」注意,這對'PySide'不起作用,你會得到一個'OverflowError:Python int太大而不能轉換成C long'異常 – 2016-06-01 18:50:57
我知道這是一個古老的答案,但來到這裏,從谷歌。這是我與pyside 1.2.4解決方案基於有所關Techniquab的解決方案,但沒有整數溢出問題:
from PySide import QtCore, QtGui
from numpy import base_repr
from PySide.QtGui import QRegExpValidator
class QBaseSpinBox(QtGui.QAbstractSpinBox):
valueChanged = QtCore.Signal(int)
_value = 0
default_value = 0
base = 10
def __init__(self, parent=None):
self.setRange(None, None)
QtGui.QAbstractSpinBox.__init__(self, parent)
self.set_base(self.base)
self.lineEdit().setValidator(QRegExpValidator(self))
self.default_value = self.value()
self.lineEdit().textChanged.connect(self.textChanged)
self.lineEdit().setContextMenuPolicy(QtCore.Qt.CustomContextMenu);
self.lineEdit().customContextMenuRequested.connect(self.contextMenuRequested)
@QtCore.Slot()
def contextMenuRequested(self, point):
menu = self.lineEdit().createStandardContextMenu() #QtGui.QMenu()
actionDefault = menu.addAction("&Set Default Value of %s" % self.textFromValue(self.default_value),
shortcut=QtCore.Qt.CTRL | QtCore.Qt.Key_D) #QtGui.QKeySequence("Ctrl+D")))
menu.insertSeparator(actionDefault)
actionDefault.triggered.connect(self.menuActionDefault_triggered)
menu.exec_(self.mapToGlobal(point))
@QtCore.Slot()
def menuActionDefault_triggered(self):
self.setValue(self.default_value)
def value(self):
return self._value
def setValue(self, value):
if self.validate(value) == QtGui.QValidator.Invalid:
self.setValue(self._value)
return
changed = False
if self._value != value:
changed = True
self._value = value
self.lineEdit().setText(self.textFromValue(value))
if changed:
self.valueChanged.emit(self._value)
@QtCore.Slot()
def stepBy(self, value):
self.setValue(self._value + value)
QtGui.QAbstractSpinBox.stepBy(self, self._value)
def stepEnabled(self):
return QtGui.QAbstractSpinBox.StepDownEnabled | QtGui.QAbstractSpinBox.StepUpEnabled
@QtCore.Slot()
def textChanged(self, text):
try:
self.setValue(int(text, self.base))
except:
self.setValue(self._value)
def setRange(self, _min, _max):
self.minimum = _min if _min != None else 0
self.maximum = _max if _max != None else 0xFFFFFFFFFFFFFFFF
def validate(self, input):
if not input:
return QtGui.QValidator.Intermediate
try:
try:
value = int(input, self.base)
except TypeError:
value = input
if not (self.minimum <= input <= self.maximum):
raise Exception()
except Exception as ex:
return QtGui.QValidator.Invalid
return QtGui.QValidator.Acceptable
def valueFromText(self, text):
return int(text, self.base)
def textFromValue(self, value):
return base_repr(value, self.base).upper()
def set_default_value(self, value):
self.default_value = int(value)
#self.setValue(self.default_value)
self.set_base(self.base) # Redo the tooltip
def set_base(self, base):
self.base = base
min = self.textFromValue(self.minimum)
max = self.textFromValue(self.maximum)
default = self.textFromValue(self.default_value)
self.lineEdit().setToolTip("Base %d\nRange: %s-%s\nDefault Value: %s" % (self.base, min, max, default))
如果您不需要完整的32位,你可以做到這一點很簡單的是這樣的:
#pragma once
#include <QSpinBox>
class PaddedSpinBox : public QSpinBox
{
public:
PaddedSpinBox(QWidget *parent = 0) : QSpinBox(parent)
{
}
protected:
QString textFromValue(int value) const override
{
// Pad to the width of maximum().
int width = QString::number(maximum(), displayIntegerBase()).size();
return QString("%1").arg(value, width, displayIntegerBase(), QChar('0')).toUpper();
}
};
在表單設計器(或其他),那麼你只需設置:
prefix
:0x
displayIntegerBase
:16maximum
:255(或其他)
如果您需要完整的32位,你將不得不使用鑄造的招數,或者只是使用行編輯。
- 1. 輸入十六進制並用C++讀取十六進制
- 2. 用戶輸入十六進制到十六進制陣列
- 3. C#功能:輸入= INT十進制值,輸出=字節的十六進制值
- 4. QValidator十六進制輸入
- 5. 將十六進制掃描(scanf)從unsigned int數組轉換爲十進制
- 6. 帶有十六進制編碼輸入的Openssl摘要
- 7. 將十六進制字符串轉換爲unsigned int問題C++
- 8. 將十六進制緩衝區轉換爲unsigned int
- 9. 如何從十六進制NSString得到十進制整數int
- 10. 輸入十六進制到的argv [1]
- 11. 十六進制的輸入掩碼
- 12. jQuery UI - 用於輸入數字爲十六進制的插件?
- 13. PyQt:用於十六進制的QLineEdit輸入掩碼
- 14. Android Java CRC十六進制輸入
- 15. openssl以十六進制輸入bash
- 16. 將輸入視爲十六進制值
- 17. 十六進制串&十六進制
- 18. 如何在十六進制字符數組中插入十六進制值
- 19. 十六進制
- 20. 將十六進制轉換爲十進制的方法 - 輸入非十六進制數時程序不正確
- 21. C++十進制到十六進制(int到char)
- 22. 將int轉換爲帶前導零的十六進制
- 23. 用於大數字的十進制到十六進制的Python
- 24. 將十進制轉換爲十六進制和十六進制
- 25. 使用十進制或十六進制
- 26. 十六進制NSString爲int值
- 27. 十六進制爲int在Java
- 28. 轉換十六進制到int
- 29. 插入十六進制值
- 30. 無符號字符十六進制到int十進制轉換C++
接受你的答案。 – nnb 2014-10-27 06:38:49