QPainter#drawText在initializeDb中出现故障

时间:2016-10-28 21:33:31

标签: c++ qt qt5 qpainter qimage

使用Qt 5.7,Windows 7,MinGW 32位,以下程序:

#include <QImage>
#include <QPainter>

int main () {
    QImage i(100, 100, QImage::Format_RGB888);
    QPainter p(&i);
    p.drawText(0, 0, "abc"); // line 7
}

p.drawText调用上出现段错误,给出以下堆栈跟踪,以initializeDb结束:

1  initializeDb                  qfontdatabase.cpp 896  0x7930ed0 
2  QFontDatabase::findFont       qfontdatabase.cpp 2640 0x79361f6 
3  QFontDatabase::load           qfontdatabase.cpp 2795 0x7936b5e 
4  QFontPrivate::engineForScript qfont.cpp         215  0x79194ff 
5  QTextEngine::fontEngine       qtextengine.cpp   2094 0x793d24b 
6  QTextEngine::shapeText        qtextengine.cpp   1000 0x7938c0b 
7  QTextEngine::shape            qtextengine.cpp   1534 0x793b090 
8  QTextEngine::shapeLine        qtextengine.cpp   938  0x793884a 
9  QPainter::drawText            qpainter.cpp      5877 0x7a3dc91 
10 QPainter::drawText            qpainter.cpp      5700 0x7a3cfe6 
11 QPainter::drawText            qpainter.h        890  0x402a1e  
12 main                          main.cpp          7    0x4016b6  

为什么会发生这种情况,如何让它不发生?

.pro文件,完整性:

QT += core gui    
CONFIG += c++11
TARGET = untitled18
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app    
SOURCES += main.cpp

这适用于生成图像的命令行实用程序。

注意:添加QCoreApplication并没有什么区别。

1 个答案:

答案 0 :(得分:2)

查看Qt源代码可以解决这类问题。

qfontdatabase.cpp的第896行(您的堆栈跟踪显示发生崩溃的位置)如下所示:

static QPlatformIntegration *platformIntegration()
{ return platform_integration; }

....因此很可能由于某种原因,platformIntegration()或fontDatabase()返回NULL。

通过源代码,我们看到QGuiApplicationPrivate :: platformIntegration()在这里定义,位于gui / kernel / qguiapplication.h的第103行:

QGuiApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name, arguments, argc, argv, platformPluginPath);

...如果尚未设置platform_integration变量尚未指向任何有效对象,则该方法肯定会返回NULL。

稍微多一点,我们发现设置platform_integration静态变量的唯一地方是gui / kernel / qguiapplication.cpp的第1094行:

@Entity
@Table(name = "CITA", schema = "COLINASCO")
public class Cita implements Serializable{
    private long id;
    private Date fecha;
    private Time hora;
    private Paciente paciente;
    private Empleado empleado;
    private Set<Tratamiento> listaTratamientos;

    public Cita() {
        fecha = null;
        hora = null;
        paciente = null;
        empleado = null;
        listaTratamientos = null;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "CITA_ID", nullable = false, unique = true)
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @Column(name = "FECHA", nullable = false)
    public Date getFecha() {
        return fecha;
    }

    public void setFecha(Date fecha) {
        this.fecha = fecha;
    }

    @Column(name = "HORA", nullable = false)
    public Time getHora() {
        return hora;
    }

    public void setHora(Time hora) {
        this.hora = hora;
    }

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "PACIENTE_ID")
    public Paciente getPaciente() {
        return paciente;
    }

    public void setPaciente(Paciente paciente) {
        this.paciente = paciente;
    }

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "EMPLEADO_ID")
    public Empleado getEmpleado() {
        return empleado;
    }

    public void setEmpleado(Empleado empleado) {
        this.empleado = empleado;
    }

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "CITA_TRATAMIENTO", joinColumns = {@JoinColumn(name = "CITA_ID")},
            inverseJoinColumns = {@JoinColumn(name = "TRATAMIENTO_ID")},
    uniqueConstraints = {@UniqueConstraint(columnNames = {"CITA_ID","TRATAMIENTO_ID"}, name = "CITA_TRATAMIENTO_PK")},
    schema = "COLINASCO")
    public Set<Tratamiento> getListaTratamientos() {
        return listaTratamientos;
    }

    public void setListaTratamientos(Set<Tratamiento> listaTratamientos) {
        this.listaTratamientos = listaTratamientos;
    }
}

...这是一个名为init_platform()的静态函数的一部分,它从QGuiApplicationPrivate :: createPlatformIntegration()调用,它本身是从QGuiApplicationPrivate类的各种方法调用的。

但是当然除非/直到创建QGuiApplicationPrivate对象,否则不能调用任何QGuiApplicationPrivate方法,除非/直到你创建了一个QGuiApplication对象,否则这种方法可能不会发生。

总而言之......看起来Rinold是正确的,在尝试使用QPainter绘制文本之前,需要首先实例化QGuiApplication(或QApplication,它是QGuiApplication的子类)对象。