化石原创文章,转载请注明来源并保留原文链接


Qt的上下文菜单实现方式要根据Widget的contextMenuPolicy(这是Widget的一个成员变量)来定。

1、自定义菜单

先在Widget初始化的时候调用

setContextMenuPolicy(Qt::CustomContextMenu);

指定该widget的上下文菜单是自定义的。

这里的自定义并不是说上下文菜单随意摆置内容-菜单怎么显示本来就是自定义。而是:实现上下文的方式或者说流程不同。

这里的流程是:

当上下文的行为(大多是右键点击)产生时,Qt底层会发出

 customContextMenuRequested() 

这个信号。

该信号定义在QWidget中:

 Q_SIGNALS:
     void customContextMenuRequested(const QPoint &pos);

所以,我们要能得到上下文信号,只要做一个slot就可以。

这样,自定义形式下,就三步:

a、setContextMenuPolicy(Qt::CustomContextMenu);

b、连接信号和插槽,比如:

connect(this, SIGNAL (customContextMenuRequested(const QPoint&)), this, SLOT (contextMenu(const QPoint&)));

c、在插槽里实现具体的菜单内容,位置是信号传过来的。

应用场合:

QTableView继承类的上下文菜单

2、默认上下文菜单

这个相当于用

 setContextMenuPolicy(Qt::DefaultContextMenu ); 

此种状况下,如果Widget中有重写的

void contextMenuEvent(QContextMenuEvent* event);

方法。这个方法在对应的时候就会激发。


化石原创文章,转载请注明来源并保留原文链接



化石原创文章,转载请注明来源并保留原文链接


做一个上下文菜单,大多菜单QAction引发的方法,都进入同一个触发方法,这样在方法中,这样能少写很多方法,代码也会简洁很多。引起的一个问题是:在这个方法中,必须知道是哪个QAction引发。

sender()方法就用来解决该问题,只要是QObject的子类,都包含该方法,这样,如果知道是QAction引发的方法调用,只要把send()返回的值强转为QAction,就能得到该QAction的text,如果text就能识别,那么就知道是哪个QAction激发了方法。

    QAction* action = qobject_cast<QAction*> (sender());
    int size = action->text().toInt();


化石原创文章,转载请注明来源并保留原文链接



化石原创文章,转载请注明来源并保留原文链接


本文适用于使用CKEditor5的官方默认向导生成的CKEditor5,但也可能对其他方式的有同样的意义。

对于上传图片这一块,这个默认的带上了ckfinder作为前端的上传插件。

假设我们的上传api,url是:/api/upload

那么,客户端只要这么配置:

var uploadApi = document.location.origin + "/api/upload";

ClassicEditor.create( document.querySelector( '#article-editor' ), {

				toolbar: {
					items: [
						'heading',
						'|',
						'bold',
						'italic',
						'link',
						'bulletedList',
						'numberedList',
						'|',
						'indent',
						'outdent',
						'|',
						'imageUpload',
						'blockQuote',
						'insertTable',
						'mediaEmbed',
						'undo',
						'redo'
					]
				},
				language: 'en',
				image: {
					toolbar: [
						'imageTextAlternative',
						'imageStyle:full',
						'imageStyle:side'
					]
				},
				ckfinder: {
                    uploadUrl: uploadApi,
				},
				table: {
					contentToolbar: [
						'tableColumn',
						'tableRow',
						'mergeTableCells'
					]
				},
				licenseKey: '',

			} )
			.then( editor => {
				window.editor = editor;
			} )
			.catch( error => {
				console.error( 'Oops, something gone wrong!' );
				console.error( 'Please, report the following error in the https://github.com/ckeditor/ckeditor5 with the build id and the error stack trace:' );
				console.warn( 'Build id: k2i30chx32nf-8o65j7c6blw0' );
				console.error( error );
			} );

其实对于前端,就是给ckfinder配上一个url,就这么简单。

后台这块ASP.net,Java,PHP官方有文档,不过说实话一点都不友好。所以自给自足:

    @PostMapping("/api/upload")
    private String uploadImage(@RequestParam MultipartFile[] upload) {
        String originalFileName = upload[0].getOriginalFilename();
        String fileExtensionName = originalFileName.substring(originalFileName.lastIndexOf("."), originalFileName.length()).toLowerCase();;//上传图片的文件扩展名

        String newFileName = java.util.UUID.randomUUID().toString()+fileExtensionName;
        String uploadPath = imageUploaPath;
        String imageUrl = imageUploaPath + newFileName;
        File pathFile = new File(uploadPath);
        if (!pathFile.exists()) { // 如果路径不存在,创建
            pathFile.mkdirs();
        }
        try {
            File dest = new File(imageUrl);
            upload[0].transferTo(dest);
        } catch (IOException e) {

        }

        JSONObject jo = new JSONObject();
        jo.put("uploaded", true);
        jo.put("url", newFileName);

        return jo.toJSONString();
    }

代码是SpringBoot工程萃取出来的,已经删去了不必要的代码。尽量只展现这部分的有效信息。

最有用的信息是返回值格式:ckeditor5希望的格式其实是这样的json

{
    "uploaded": true,
    "url": "xxxxx"
}

这个是成功的返回格式。如果错误,则是下面:

 {
    "uploaded": false,
    "error": {
        "message": "xxxx"
    }
} 

代码中,imageUploadPath是@Autowired来的

@Value("${web.upload-path}")
private String imageUploaPath;

在application.properties是这样:

web.upload-path=f:/imageUpload/
spring.mvc.static-path-pattern=/**
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${web.upload-path}

那个JSONObject用了Maven里面的json-simple

<!-- https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple -->
<dependency>
    <groupId>com.googlecode.json-simple</groupId>
    <artifactId>json-simple</artifactId>
    <version>1.1.1</version>
</dependency>

化石原创文章,转载请注明来源并保留原文链接



化石原创文章,转载请注明来源并保留原文链接


做一个随浏览器大小始终居中的进度条,使用了下面的代码:

<div id="loadingContainer" style="position: absolute; width: 100%; height: 90%;" >
	<div class="row h-100 align-items-center justify-content-center">
		<div class="row">
			<div class="col">
				<p id="loadingProgress" style="color: red; font-size: 2rem;">0%</p>
			</div>
		</div>
	</div>
</div>

第3行开始的是进度条本身,第1行和第2行是关键。第1行的height百分比,可以用来调节在高度上的居中感觉。


化石原创文章,转载请注明来源并保留原文链接



化石原创文章,转载请注明来源并保留原文链接


在mouted方法中,如果用了DOM的回调方法,而这个方法需要用到methods里定义的方法,那么this不能直接被使用。我们需要在mouted中,先把this赋值给一个变量,而后在这个回调中就能使用到方法。

比如下面的例子:

  methods : {
    
    changeFontSize () {
        var initBannerTitleFontSize = 80, initBannerTitleMarginTop = 70, initBannerTitleMarginBottom = 20;
        var initBannerDescFontSize = 30, initBannerDescLineHeight = 45;

        var height = document.getElementById('bannerbg').clientHeight;
        var percent = height / 300;

        var bannerTitle = document.getElementById('bannertitle');
        var bannerDesc = document.getElementById('bannerdesc');

        bannerTitle.style.fontSize = percent * initBannerTitleFontSize + "px";
        bannerTitle.style.marginTop = percent * initBannerTitleMarginTop + "px";
        bannerTitle.style.marginBottom = percent * initBannerTitleMarginBottom + "px";
        
        bannerDesc.style.fontSize = percent * initBannerDescFontSize + "px";
        bannerDesc.style.lineHeight  = percent * initBannerDescLineHeight + "px";
    },
  },
  mounted() {
    var that = this;
    
    if(document.body.clientWidth<800){
      this.isPC = false;
    }

    document.getElementById('bannerbg').addEventListener('load', function() {
      that.changeFontSize();
    });

    window.onresize = () => {
        return (() => {
          this.changeFontSize();
        })();
    };
  }

这里的that本地变量,就执行this对象,在回调中使用完全没有问题。在javascript中,这个是很常见的手法。


化石原创文章,转载请注明来源并保留原文链接