qml 구현 채 팅 인터페이스
102682 단어 QT 프로 그래 밍
자신 이 필요 로 하 는 기능 을 추 가 했 습 니 다. listview 의 delegate 문 자 는 마우스 로 선택 하고 복사 할 수 있 으 며 키보드 ctrl + c 복사, item 의 삭 제 를 받 을 수 있 습 니 다. 마우스 가 맨 위로 미 끄 러 질 때 더 많은 item 을 불 러 오고 상호작용 채 팅 방식 을 지양 하 며 푸 시 에 만 사용 할 수 있 습 니 다. 상기 링크 를 참고 하 는 것 을 권장 합 니 다.
직접 코드 붙 이기:
import QtQuick 2.6
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.0
Rectangle {
id: root
color: "#f5f5f5"
function add_message(timetext,issame,text,who,istip,type,id)
{
if(text.length <= 0)
{
return;
}
listView.model.insert(0, {"content": text, "send": who,"msgTime":timetext,"same":issame,"tip":istip,
"send_type": type,"id": id});
//verScrollBar.increase()
//
verScrollBar.setPosition(1.0)
}
function add_more_message(timetext,issame,text,who,istip,type,id)
{
if(text.length <= 0)
{
return;
}
var count=listView.model.count
listView.model.insert(count, {"content": text, "send": who,"msgTime":timetext,"same":issame,"tip":istip,
"send_type": type,"id": id});
//verScrollBar.increase()
//verScrollBar.setPosition(1.0)
}
function clearListview()
{
listView.model.clear()
}
function re_edit_item(index)
{
var count=listView.model.count
if(count>0){
listView.model.remove(index,1)
}
}
property bool showtip: false
function show_tip()
{
showtip=true
}
function hide_tip()
{
showtip=false
}
ColumnLayout {
id:page
anchors.fill: parent
// focus true
focus: true
// messageText ,
//page ctrl+c messagetext copy
signal ctrl_c()
Keys.onPressed: {
if((event.modifiers===Qt.ControlModifier) && (event.key===Qt.Key_C)){
//
page.ctrl_c()
}
event.accepted=true
}
Rectangle {
id:tiprect
width: tiptext.implicitWidth+10
height: 30
color: "#f5f5f5"
anchors.horizontalCenter: parent.horizontalCenter
visible:showtip
Label {
id: tiptext
text: " "
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: "#1f61ff"
font.family: " "
font.pointSize: 9
anchors.fill: parent
anchors.margins:0
}
}
ListView {
id: listView
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins:14
Layout.rightMargin: 0
displayMarginBeginning: 40
displayMarginEnd: 40
verticalLayoutDirection: ListView.BottomToTop
spacing:14
model:ListModel{}
delegate: Column {
anchors.left: parent.left
spacing: 14
width: parent.width
property bool sendmessage: send
property bool sameTime: same
//
Rectangle {
width: timetext.implicitWidth+10
height: timetext.implicitHeight+2
color: tip ? "lightgrey" : "#d1cece"
anchors.horizontalCenter: parent.horizontalCenter
visible: !same
Label {
id: timetext
text: msgTime
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: tip ? "red" : "white"
font.family: " "
font.pointSize: 9
anchors.fill: parent
anchors.margins:0
}
}
//
Row {
id: messageRow
spacing: 6
anchors.left: parent.left
visible: !tip
//
Image {
id: avatarLeft
height: 36
width: height
source: "qrc:/image/touxiang.jpg"
}
//
Rectangle {
width: Math.min(messageText.implicitWidth +14, listView.width -98)
height: messageText.implicitHeight + 16
color: send ? "#9dea6a" : "#eeeeee"
radius: 3
TextEdit {
id: messageText
text: content
font.family: " "
//color: "#9dea6a"
font.pointSize: 11
anchors.fill: parent
anchors.topMargin: 9
anchors.bottomMargin: 7
anchors.rightMargin: 7
anchors.leftMargin: 7
wrapMode: TextEdit.Wrap
enabled: true
readOnly: true
selectByKeyboard: true
selectByMouse: true
selectedTextColor: "white"
persistentSelection:true
selectionColor: "#3396FF"
// listview
Drag.active: text_area.drag.active
}
// ,
MouseArea{
id:text_area
width: parent.width
height: parent.height
acceptedButtons: Qt.LeftButton|Qt.RightButton
// , ,
drag.target: messageText
hoverEnabled: true
property int _startpos: 0
property int _endpos: 0
property bool canselect: false
onClicked: {
// = ,js
if(mouse.button===Qt.RightButton){
// ,
if(_startpos<_endpos){
messageText.select(_startpos-1,_endpos)
} else {
if(_startpos>_endpos){
messageText.select(_endpos-1,_startpos)
} else {
messageText.select(_startpos,_endpos)
}
}
// mainwindow
mainwindow.listview_item_clicked(index,id,send_type,messageText.selectedText,messageText.text)
}
}
onEntered: {
// ,
page.ctrl_c.connect(message_cpoy)
}
//
function message_cpoy(){
messageText.copy()
}
// , ,
onExited: {
messageText.deselect()
_startpos=0
_endpos=0
page.ctrl_c.disconnect(message_cpoy)
}
//
onMouseXChanged: {
if(canselect){
_endpos=messageText.positionAt(mouseX,mouseY)
// 1,
if(_startpos<_endpos){
messageText.select(_startpos-1,_endpos)
} else {
if(_startpos>_endpos){
messageText.select(_endpos-1,_startpos)
} else {
messageText.select(_startpos,_endpos)
}
}
}
}
//
onPressed: {
if(mouse.button===Qt.LeftButton){
canselect=true
_startpos=messageText.positionAt(mouseX,mouseY)
}
}
//
onReleased: {
if(mouse.button===Qt.LeftButton){
//messageText.copy()
canselect=false
}
}
}
}
}
}
ScrollBar.vertical: ScrollBar {
id: verScrollBar
}
//
onContentYChanged: {
//console.log("contenty:"+contentY)
//console.log("originy"+originY)
var x=contentY-originY
if(x==0){
mainwindow.load_more_for_chatwidget();
}
}
}
/* cpp
Connections{
target: mywindows
onShowmymsg:add_message(arg_1,arg_2,arg_3,arg_4,arg_5)
}*/
}
}
/ / cpp 의 함수: (cpp 에서 상하 문 속성 을 설정 한 후 사용 가능)
/ / quickwidget qml 불 러 오기
QUrl source("qrc:/myqml/1.qml");
// c++ qml, qml c++ Q_INVOKABLE public public
ui->quickWidget->rootContext()->setContextProperty("mainwindow",this);
//
//qmlRegisterType("io.qt.mainwindow", 1, 0, "Mwindow");
ui->quickWidget->setSource(source);
/ / 하나 추가
QQuickItem *item=ui->quickWidget->rootObject();
QVariant returnVar;
QString send_time1=QDateTime::fromString(send_time,"yyyyMMddhhmmss").toString("hh:mm");
QVariant arg1 = send_time1;
QVariant arg2;
QVariant arg3 =send_text;
QVariant arg4 =true;
QVariant arg5 =false;
QVariant arg6="no_reedit";
QVariant arg7=-1;
if(send_time1==lastSend_time)
{
arg2= true;
}
else
{
arg2=false;
lastSend_time=send_time1;
}
QMetaObject::invokeMethod(item, "add_message",
Q_RETURN_ARG(QVariant, returnVar),Q_ARG(QVariant, arg1),Q_ARG(QVariant, arg2),
Q_ARG(QVariant, arg3),Q_ARG(QVariant, arg4),Q_ARG(QVariant, arg5),
Q_ARG(QVariant, arg6),Q_ARG(QVariant, arg7));
/ / cpp 의 함수
void mainwindow::listview_item_clicked(const int index, const int id, const QString sendtype,const QString selectedtext,const QString itemtext)
{
qml_id=id;
qml_index=index;
qml_sendtype=sendtype;
qml_selected_text=selectedtext;
qml_item_text=itemtext;
//qDebug()<
//qDebug()<
ui->quickWidget->customContextMenuRequested(QPoint(0,0));
}
qml 의 값 을 개인 변수 에 부여 하면 복사 및 방향 취소 기능 을 실현 할 수 있 습 니 다.
//취소QQuickItem *item=ui->quickWidget->rootObject();
QVariant returnVar;
QVariant arg1 = qml_item_index;
QMetaObject::invokeMethod(item, "re_edit_item",
Q_RETURN_ARG(QVariant, returnVar),Q_ARG(QVariant, arg1));
label_who *label_w1 = (label_who *)(ui->label_2->userData(Qt::UserRole));
//QString send_type=label_w1->send_type;
QString send_who=label_w1->send_who;
/ / 선택 한 텍스트 를 복사 합 니 다. qml 파일 에서 선택 한 후 ctrl + c 를 누 르 면 직접 복사 할 수 있 습 니 다.
void mainwindow::copy_content(){
QClipboard *clipboard=QApplication::clipboard();
clipboard->setText(qml_selected_text,QClipboard::Clipboard);
}
void mainwindow::load_more_for_chatwidget(){
if(last_query_number<5){ // 5
QQuickItem *item=ui->quickWidget->rootObject();
QString current_to_usr_name=ui->listWidget->currentItem()->data(Qt::UserRole+1).toString();
QString item_type=ui->listWidget->currentItem()->data(Qt::UserRole).toString();
QString item_mail=ui->listWidget->currentItem()->data(Qt::UserRole+2).toString();
//
QSqlQuery sql_query;
QString select_his_content;
if(item_type=="user")
{
int last_number=last_query_number*10;
//limit ...
select_his_content="select send_time,send_text from his_tousr "
"where tousrmail=:mail "
"order by send_time desc "
"limit 10 offset :last_number";
sql_query.prepare(select_his_content);
sql_query.bindValue(":mail",item_mail);
sql_query.bindValue(":last_number",last_number);
}
else
{
if(item_type=="group")
{
int last_number=last_query_number*10;
select_his_content="select send_time,send_text from his_group "
"where usrgroupname=:groupname "
"order by send_time desc "
"limit 10 offset :last_number";
sql_query.prepare(select_his_content);
sql_query.bindValue(":groupname",current_to_usr_name);
sql_query.bindValue(":last_number",last_number);
}
}
if(sql_query.exec())
{
while(sql_query.next())
{
QString send_time=sql_query.value(0).toString();
QString his_content=sql_query.value(1).toString();
// ,
QString yestoday_date=QDateTime::currentDateTime().addDays(-1).toString("yyyyMMdd");
QString today_date=QDateTime::currentDateTime().toString("yyyyMMdd");
if(send_time.left(8)==today_date)
{
send_time=(send_time.mid(8,2)+":"+send_time.mid(10,2));
}
else {
if(send_time.left(8)==yestoday_date)
{
send_time=" "+send_time.mid(8,2)+":"+send_time.mid(10,2);
}
else
{
if(send_time.left(4)==today_date.left(4))
{
QDateTime send_time1=QDateTime::fromString(send_time,"yyyyMMddhhmmss");
send_time=send_time1.toString("M dd hh:mm");
}
else
{
QDateTime send_time1=QDateTime::fromString(send_time,"yyyyMMddhhmmss");
send_time=send_time1.toString("yyyy M dd hh:mm");
}
}
}
QVariant returnVar;
QVariant arg1 = send_time;
QVariant arg2;
QVariant arg3 =his_content;
QVariant arg4 =true;
QVariant arg5 =false;
QVariant arg6="no_reedit";
QVariant arg7=-1;
if(send_time==lastSend_time)
{
arg2= true;
}
else
{
arg2=false;
lastSend_time=send_time;
}
QMetaObject::invokeMethod(item, "add_more_message",
Q_RETURN_ARG(QVariant, returnVar),Q_ARG(QVariant, arg1),Q_ARG(QVariant, arg2),
Q_ARG(QVariant, arg3),Q_ARG(QVariant, arg4),Q_ARG(QVariant, arg5),
Q_ARG(QVariant, arg6),Q_ARG(QVariant, arg7));
ui->quickWidget->repaint();
}
last_query_number++;
}
else{
qDebug()<<sql_query.lastError();
}
} else {
qDebug()<<"nidaye";
QQuickItem *item=ui->quickWidget->rootObject();
QMetaObject::invokeMethod(item,"show_tip");
}
}
/ / 기록 해 주세요.